09.Java面向对象三大特性_多态

一、多态

1.1 概念

生活中的多态  

  • 上课铃响了,上体育课的学生跑到操场上站好,上语文课的学生在教室里坐好,同样是学生,表现形式存在多样化
  • F1按键在不同的窗口下,意义不同,展示效果不同

程序中的多态

  • 同一个对象,在不同时刻表现出来的不同的形态
  • 比如
    • 我们可以说猫是猫:猫 cat = new 猫();
    • 我们也可以说猫是动物: 动物 animal = new 猫();
    • 这里猫在不同的时刻表现出了不同的形态,这就是多态

多态的前提和体现

  • 有继承或实现关系
  • 有方法重写
  • 有父类的引用指向子类的对象

代码体现demo1

 1 package demo1;
 2 
 3 public class Animal {
 4  public void eat() {
 5      System.out.println("动物吃东西");
 6  }
 7 }
 8 
 9 
10 public class Cat extends Animal {
11     @Override
12     public void eat() {
13         System.out.println("猫吃鱼");
14     }
15 }
16 
17 
18  /**
19   * 多态:
20   *     同一个对象,在不同时刻表现出来的不同的形态
21   * 举例:猫
22   *      我们可以说猫是猫:猫 cat = new 猫();
23   *      我们也可以说猫是动物:动物 animal = new 猫();
24   *      这里猫在不同时刻表现出来了不同的形态,这就是多态
25   *多态的前提和体现
26   *        有继承/实现关系
27   *        有方法重写
28   *        有父类引用指向子类对象
29   * @author 单sir的电脑
30   *
31   */
32 public class AnimalDemo {
33     public static void main(String[] args) {
34         Animal a = new Cat();
35         a.eat();
36     }
37 }

1.2 多态中实例变量和实例方法的访问特点

  • 成员变量 编译看左边,运行看左边
  • 成员方法 编译看左边,运行看右边
  为什么成员变量和成员方法访问不一样呢?
  • 因为成员方法有重写,而成员变量没有

代码体现demo2

 1 package demo2;
 2 
 3  /**
 4   * @author 单sir的电脑
 5   * 测试类
 6   */
 7 public class AnimalDemo {
 8     public static void main(String[] args) {
 9         //有父类引用指向子类对象
10         Animal a = new Cat();
11         System.out.println(a.age);
12 //        System.out.println(a.weight);//报错,为何?因为编译看左边,运行看左边
13         a.eat();
14 //        a.playGame();//报错,为何?因为编译看左边,运行看右边
15     }
16 }
17 
18 public class Animal {
19     public int age = 40;
20  public void eat() {
21      System.out.println("动物吃东西");
22  }
23 }
24 
25 public class Cat extends Animal {
26     public int age = 20;
27     public int weight = 10;
28     @Override
29     public void eat() {
30         System.out.println("猫吃鱼");
31     }
32     
33     public void playGame() {
34         System.out.println("猫捉迷藏");
35     }
36 }

 

1.3 多态的好处与弊端

  多态的好处:提高的程序的扩展性
  具体体现:定义方法的时候,使用父类作为参数,将来使用的时候,使用具体的子类参与操作
  多态的弊端:不能使用子类特有功能,但可以通过类型强转进行访问
代码体现demo3
 1 package demo3;
 2 
 3  /**
 4   * @author 单sir的电脑
 5   * 测试类
 6   */
 7 public class AnimalDemo {
 8     public static void main(String[] args) {
 9         //创建动物操作类的对象,调用方法
10         AnimalOperator ao = new AnimalOperator();
11         Cat c = new Cat();
12         ao.useAnimal(c);
13         
14         Dog d = new Dog();
15         ao.useAnimal(d);
16         
17         Pig p =  new Pig();
18         ao.useAnimal(p);
19     }
20 }
21 
22 public class Animal {
23  public void eat() {
24      System.out.println("动物吃东西");
25  }
26 }
27 
28 public class Cat extends Animal {    
29     @Override
30     public void eat() {
31         System.out.println("猫吃鱼");
32     }
33 }
34 
35 /*
36  * 动物操作类
37  */
38 public class AnimalOperator {
39     /*public void useAnimal(Cat c) { //Cat c = new Cat();
40         c.eat();
41     }
42     
43     public void useAnimal(Dog d) { //Dog d = new Dog();
44         d.eat();
45     }*/
46     public void useAnimal(Animal a) {
47         //Animal a = new Cat();
48         //Animal a = new Dog();
49         a.eat();
50 //        a.lookDoor();报错,不能访问子类特有的方法
51     }
52 }
53 
54 public class Dog extends Animal {
55     @Override
56     public void eat() {
57         System.out.println("狗吃骨头");
58     }
59     public void lookDoor() {
60         System.out.println("狗看门");
61     }
62 }
63 
64 
65 public class Pig extends Animal {
66     @Override
67     public void eat() {
68         System.out.println("猪吃白菜");
69     }
70 }

1.4 多态中的转型

  • 向上转型
    • 从子到父
    • 父类引用指向子类对象
  • 向下转型
    • 从父到子
    • 父类引用转为子类对象

代码展示

package demo4;

public class Animal {
 public void eat() {
     System.out.println("动物吃东西");
 }
}public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
    public void playGame() {
        System.out.println("猫捉迷藏");
    }
}
/**
    向上转型
        从子到父
        父类引用指向子类对象
    向下转型
        从父到子
        父类引用转为子类对象
  *
  */
public class AnimalDemo {
    public static void main(String[] args) {
        //多态
        Animal a = new Cat(); //由父类引用指向子类对象,向上转型
        a.eat();    
        
        //创建Cat类的对象
        /*Cat c = new Cat();
        c.eat();
        c.playGame();*/
        
        //向下转型,解决多态的弊端(不能调用子类特有的方法)
        Cat c=(Cat)a;
        c.eat();
        c.playGame();
    }
}

 

1.5 多态练习题

第一题

 

 

 1 package case5;
 2 /*
 3  * 测试类
 4  */
 5 public class Test {
 6     public static void main(String[] args) {
 7         // 以多态方式分别实例化子类对象并调用eat()方法
 8         Animal a = new Dog();
 9         a.eat();
10         a = new Cat();
11         a.eat();
12         a = new Lion();
13         a.eat();
14     }
15 }
16 
17 //动物类
18 public class Animal {
19  public void eat() {
20      System.out.println("动物吃东西");
21  }
22 }
23 package case5;
24 
25 // Dog类继承Animal类 复写eat()方法
26 public class Dog extends Animal {
27     @Override
28     public void eat() {
29         System.out.println("eating bread...");
30     }
31 }
32 
33 /*
34  * Cat类继承Animal类 复写eat()方法
35  */
36 public class Cat extends Animal {
37     @Override
38     public void eat() {
39         System.out.println("eating rat...");
40     }
41 }
42 
43 //Lion类继承Animal类 复写eat()方法
44 public class Lion extends Animal {
45     @Override
46     public void eat() {
47         System.out.println("eating meat...");
48     }
49 }

第二题

1.编程要求
  • 声明一个人(Person)类,此类中定义eat()方法
  • 声明一个北方人(NorthPerson)类、南方人(SouthPerson)类,均继承自Person类,并复写了eat()方法;
  • 运用多态方式实例化子类对象并调用eat()方法打印输出信息
2.测试说明
预期输出 :
 
炒菜,吃米饭
-------------
炖菜,吃馒头
 1 package Test1;
 2 
 3 public class DuoTaiTest2 {
 4     public static void main(String[] args) {
 5         //测试
 6         //南方人
 7         Person p = new SouthPerson();
 8         p.eat();
 9         System.out.println("-------------");
10        /* SouthPerson sp = (SouthPerson)p;
11         sp.eat();
12         sp.jingShang();
13         System.out.println("-------------");
14         */
15         //北方人
16         p = new NorthPerson();
17         p.eat();
18         /*System.out.println("-------------");
19         NorthPerson np = (NorthPerson)p;
20         np.eat();
21         np.yanJiu();*/
22     }
23     
24 }
25 
26 
27 
28 public class Person {
29      public void eat() {
30           System.out.println("吃饭");
31       }
32 }
33 
34 
35 
36 public class SouthPerson extends Person {
37     public void eat() {
38         System.out.println("炒菜,吃米饭");
39     }
40     
41     public void jingShang() {
42         System.out.println("经商");
43     }
44 }
45 
46 public class NorthPerson extends Person {
47     public void eat() {
48         System.out.println("炖菜,吃馒头");
49     }
50     
51     public void yanJiu() {
52         System.out.println("研究");
53     }
54 }
第三题 
1.编程需求
编写程序实现乐手弹奏乐器。乐手可以弹奏不同的乐器从而发出不同的声音。可以弹奏的乐器包括二胡、钢琴和琵琶。
2.实现思路及关键代码:
1)定义乐器类Instrument,包括方法makeSound()
2)定义乐器类的子类:二胡Erhu、钢琴Piano和小提琴Violin
3)定义乐手类Musician,可以弹奏各种乐器play(Instrument i)
4)定义测试类,给乐手不同的乐器让他弹奏
package Test2;
/**
 * 
 * @author 单sir的电脑
 *测试类
 */
public class TestMusic {
    public static void main(String[] args) {
        /********开始********/
        //创建一个乐手
        Musician m = new Musician();
        //多态
        Instrument v = new Violin();
        v=new Piano();
        v=new Erhu();
        m.play(v);
        /*********结束*******/
    
}

package Test2;
/**
 * 
 * @author 单sir的电脑
 *乐器类
 */
public class Instrument {
     public void makeSound(){
            System.out.println("乐器发声");
        }
}
package Test2;
/**
 * 
 * @author 单sir的电脑
 *二胡类
 */
public class Erhu extends Instrument{
    @Override
    public void makeSound() {
         System.out.println("二胡在拉");
    }
}
package Test2;
/*
 * 钢琴
 */
public class Piano extends Instrument {
    public void makeSound(){
        System.out.println("弹钢琴");
    }    
}
package Test2;
/**
 * 小题琴类
 */
public class Violin extends Instrument {
    public void makeSound(){
        System.out.println("拉小题琴");
    }  
}

/*
 *乐手
*/
public class Musician {
    public void play(Instrument i){
        i.makeSound();
    }
}
第四题 
1.需求
编写程序模拟“主人”喂养“宠物”的场景
2.
提示
1: 主人类:Master 宠物类:Pet 宠物类子类:Dog、Cat、YingWu 提示
2: 主人应该有喂养的方法:feed() 宠物应该有吃的方法:eat() 只要主人喂宠物,宠物就吃。
要求:主人类中只提供一个喂养方法feed(),要求达到可以喂养各种类型的宠物。
编写测试程序: 创建主人对象 创建各种宠物对象 调用主人的喂养方法feed(),喂养不同的宠物,观察执行结果。
通过该案例,理解多态在开发中的作用。 重要提示:feed方法是否需要一个参数,参数选什么类型!!!
class Testfeed{
    public static void main(String[] args) 
    {
        //创建一个宠物对象
        Pet pet = new Pet();
        //创建一个狗对象
        Dog dog = new Dog();
        //创建一个主人对象
        Master master = new Master();
        //调用主人投喂方法
        master.feed(dog);
    }
}
class Pet{//创建宠物类让其它类都继承他
    public void eat(){//创建宠物吃方法
        System.out.println("动物在吃");
    }
}
class Dog extends Pet//创建狗类
{
    public void eat(){//覆盖父类吃方法对吃方法重写
        System.out.println("狗在吃");
    }
}
class Cat extends Pet
{
    public void eat(){
        System.out.println("猫在吃");
    }
}
class YingWu extends Pet
{
    public void eat(){
        System.out.println("鹦鹉在吃");
    }
}
class Master
{
    
    public void feed(Pet p){//此处实际上是 Pet p = new Dog();此处涉及到父类引用指向子类对象,即多态
        p.eat();//调用父类吃方法,此处为编译器识别通过,具体调用哪个子类的吃方法还要看动态绑定的那个子类是啥
    }
}
第五题 
1.需求
员工使用不同的交通工具回家
2.实现思路及关键代码:
  • 定义一个交通工具Transport类,包括run()方法
  • 定义汽车类Car,地铁类Subway,均继承Transport类,并重写run方法
  • 定义员工类,私有属性name,提供带参构造方法,并包括goHome()回家的方法
  • 测试类测试
3.
预期输出 :
员工艾编程回家了!
汽车行驶中
员工艾学习回家了!
地铁行驶中
 1 package test3;
 2 /*
 3  * 测试类
 4  */
 5 public class TestEmployeeHome {
 6       public static void main(String[] args) {
 7             Employee a = new Employee("艾编程");
 8             Car car = new Car();
 9             a.goHome(car);
10             Employee b = new Employee("艾学习");
11             Subway sub = new Subway();
12             b.goHome(sub);
13         }
14 }
15 package test3;
16 /*
17  * 交通工具类
18  */
19 public class Transport {
20     public void run() {
21         System.out.println("行驶中");
22     }
23 }
24 package test3;
25 /*
26  * 汽车类
27  */
28 public class Car extends Transport {
29     @Override
30     public void run() {
31         System.out.println("汽车行驶中");
32     }
33 }
34 package test3;
35 /*
36  * 地铁类
37  */
38 public class Subway extends Transport {
39     @Override
40     public void run() {
41         System.out.println("地铁行驶中");
42     }
43 }
44 package test3;
45 /*
46  * 员工类
47  */
48 public class Employee {
49     private String name;
50     public Employee(String name) {
51         this.name = name;
52     }
53     void goHome(Transport trans){
54         System.out.println("员工"+name+"回家了!");
55         trans.run();
56     }
57 }

posted @ 2020-10-07 22:46  单sir  阅读(289)  评论(0)    收藏  举报