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 }

浙公网安备 33010602011771号