1、多态:(polymorphism):
是具有表现多种形态能力的特征; | |
(专业化的说法:)同一个实现接口(引用类型),使用不同的实例而执行不同的操作 | |
指一个引用(类型)在不同情况下的多种状态。也可以理解成:多态是指通过指向父类的指针,来调用在不同子类中实现的方法。 | |
多态是同一个行为具有多个不同表现形式或形态的能力, 多态就是同一个接口,使用不同的实例而执行不同操作,多态性是对象多种表现形式的体现。 | |
多态的优点: 1. 消除类型之间的耦合关系 2. 可替换性 3. 可扩充性 4. 接口性 5. 灵活性 6. 简化性 7、可以减少类中代码量 8、可以提高代码的拓展性和可维护性 | 多态存在的三个必要条件: 继承 重写 父类引用指向子类对象 |
2、实现多态:
实现多态的三个要素: 编写具有继承关系的父类和子类; 子类重写父类方法; 使用父类的引用指向子类的对象; | |
实现多态的两种方式(继承和接口): | |
使用父类作为方法形参实现多态: Eg:使用多态优化主人给宠物喂食;
| 使用父类作为方法返回值实现多态: |
示例(错误):
| |
Eg1:多态的形式1:父类Pet做形参,子类做实参; | |
狗类(子类):
企鹅类(子类):
猫类(子类):
主人类:
| |
测试类: 输出结果:
| |
Eg2:多态的形式2:父类做引用类型,子类实例化; | |
测试类(其他类见eg1) | 运行结果(注意蓝色部分): |
Eg3:父类作为方法返回值,自类实例化,类型自动转换; | |
主人类(在eg1的主人类上增加代码): | 测试类(其他类见eg1): 运行结果: |
3、转换:
向上转型:子类到父类的转换; //自动转型 Pet pet=new Dog(); | Eg:向下转换: 主人类: public class Master { public void play(Pet pet){ if (pet instanceof Dog) { //如果传入的是狗狗 Dog dog = (Dog) pet; dog.catchingFlyDisc(); }else if (pet instanceof Penguin) { //如果传入的是企鹅 Penguin pgn = (Penguin) pet; pgn.swimming(); } } } | |
向下转型:父类到子类的转换(强制类型转换): ●instanceof运算符:instanceof通常和强制类型转换结合使用 语法: 对象 instanceof 类或接口 | ||
Eg1:实现宠物玩的方法: | ||
子类和宠物类:
| ||
主人类: | 测试类: | 输出结果: |
Eg2: public class Test { public static void main(String[] args) { show(new Cat()); // 以 Cat 对象调用 show 方法 show(new Dog()); // 以 Dog 对象调用 show 方法 Animal a = new Cat(); // 向上转型 a.eat(); // 调用的是 Cat 的 eat Cat c = (Cat)a; // 向下转型 c.work(); // 调用的是 Cat 的 catchMouse } public static void show(Animal a) { a.eat(); // 类型判断 if (a instanceof Cat) { // 猫做的事情 Cat c = (Cat)a; c.work(); } else if (a instanceof Dog) { // 狗做的事情 Dog c = (Dog)a; c.work(); } } } abstract class Animal { abstract void eat(); } class Cat extends Animal { public void eat() { System.out.println("吃鱼"); } public void work() { System.out.println("抓老鼠"); } } class Dog extends Animal { public void eat() { System.out.println("吃骨头"); } public void work() { System.out.println("看家"); } } |
4、 附加:
●父类引用指向子类对象,引用对象只能调用子类重写父类的方法并不能调用子类特有的方法。不然会报错; ●实现多态的条件:继承的存在、子类重写父类的方法、父类引用变量指向子类对象; |
●子类转换为父类(将一个父类的引用指向一个子类对象),称为向上转型; ●一个类继承父类,且都有方法重载的过程,在调用的时候如果该子类有该方法,则用该子类方法,如果该子类没有该方法则调用父类的该方法; ●继承体系下,如果没有用super关键字指定调用属性和方法,先在子类中,再去父类找; ●Java中的继承和多态。用父类声明,实例化父类对象,调用的是父类中的方法。 |
用子类声明,实例化子类,调用的是子类中的方法。 用父类声明,实例化子类,调用的是子类中的重写方法。 |
●子类对象赋值给父类引用,此时调用的方法是被子类重写的方法。 |