|
| 1 | +# 第5章:继承 |
| 2 | + |
| 3 | +Q:谈一谈多态? |
| 4 | + |
| 5 | +A:Java中实现多态有两种方式: |
| 6 | + |
| 7 | +- 继承,子类重写父类的方法 |
| 8 | +- 接口,类实现接口并重写接口中的方法 |
| 9 | + |
| 10 | +用父类和接口声明对象的引用变量,该变量能指向父类或子类,能指向实现类,这就是多态(polymorphism)。 |
| 11 | + |
| 12 | +在程序运行期间,能自动选择调用哪个方法(动态绑定,dynamic binding),如:引用变量用父类声明,调用子类重写父类的**同名方法时**,若引用变量指向父类,调用父类的方法;若指向子类时调用子类的方法。 |
| 13 | + |
| 14 | +**通常**:多态与`instanceof`关键字合用,可对父类及其所有子类,实现接口的类进行通用处理,使程序有良好的扩展性。(见实例2) |
| 15 | + |
| 16 | +1)实例1 |
| 17 | + |
| 18 | +```java |
| 19 | +// 父类:Employee |
| 20 | +public double getSalary() { |
| 21 | + System.out.println("父类:getSalary()"); |
| 22 | + return salary; |
| 23 | +} |
| 24 | + |
| 25 | +// 子类:Manager |
| 26 | +public double getSalary() { |
| 27 | + System.out.println("子类:getSalary()"); |
| 28 | + double baseSalary = super.getSalary();// 调用父类getSalary() |
| 29 | + return baseSalary + bonus; |
| 30 | +} |
| 31 | +``` |
| 32 | + |
| 33 | +```java |
| 34 | +// Employee -> Manager |
| 35 | +Employee e = new Manager("Test", 80000, 1987, 12, 15); |
| 36 | +e.getSalary(); // 调用子类方法 |
| 37 | + |
| 38 | +e = new Employee("666", 6666, 1990, 3, 16); |
| 39 | +e.getSalary(); // 调用父类方法 |
| 40 | + |
| 41 | +// 输出 |
| 42 | +子类:getSalary() |
| 43 | +父类:getSalary() |
| 44 | +80000.0 |
| 45 | +------------------ |
| 46 | +父类:getSalary() |
| 47 | +6666.0 |
| 48 | +``` |
| 49 | + |
| 50 | + |
| 51 | + |
| 52 | +2)实例2 |
| 53 | + |
| 54 | +多态存在的三个必要条件 |
| 55 | + |
| 56 | +- 继承 |
| 57 | +- 重写 |
| 58 | +- 父类引用指向子类对象 |
| 59 | + |
| 60 | +比如:`Parent p = new Child();` |
| 61 | + |
| 62 | +当使用多态方式:p调用方法时,**首先**检查父类中是否有该方法,如果没有,则编译错误;如果有,**再去调用子类的同名**方法。 |
| 63 | + |
| 64 | +```java |
| 65 | +package com.ch05.inheritance; |
| 66 | + |
| 67 | +public class Test { |
| 68 | + public static void main(String[] args) { |
| 69 | + show(new Cat()); // 以 Cat 对象调用 show 方法 |
| 70 | + show(new Dog()); // 以 Dog 对象调用 show 方法 |
| 71 | + |
| 72 | + Animal a = new Cat(); // 向上转型 |
| 73 | + a.eat(); // 调用的是 Cat 的 eat |
| 74 | + Cat c = (Cat)a;// 向下转型 |
| 75 | + c.work();// 调用的是 Cat 的 work |
| 76 | + } |
| 77 | + |
| 78 | + public static void show(Animal a) { |
| 79 | + a.eat();// 父类引用指向子类变量,调用子类的eat方法 |
| 80 | + // 类型判断 |
| 81 | + if(a instanceof Cat) { // 猫做的事情 |
| 82 | + Cat c = (Cat)a; |
| 83 | + c.work(); |
| 84 | + }else if (a instanceof Dog) { // 狗做的事情 |
| 85 | + Dog c = (Dog)a; |
| 86 | + c.work(); |
| 87 | + } |
| 88 | + } |
| 89 | +} |
| 90 | + |
| 91 | +abstract class Animal{ |
| 92 | + abstract void eat(); |
| 93 | +} |
| 94 | + |
| 95 | +class Cat extends Animal{ |
| 96 | + public void eat() { |
| 97 | + System.out.println("吃鱼"); |
| 98 | + } |
| 99 | + public void work() { |
| 100 | + System.out.println("抓老鼠"); |
| 101 | + } |
| 102 | +} |
| 103 | + |
| 104 | +class Dog extends Animal{ |
| 105 | + public void eat() { |
| 106 | + System.out.println("吃骨头"); |
| 107 | + } |
| 108 | + public void work() { |
| 109 | + System.out.println("看家"); |
| 110 | + } |
| 111 | +} |
| 112 | + |
| 113 | +// 输出 |
| 114 | +吃鱼 |
| 115 | +抓老鼠 |
| 116 | +吃骨头 |
| 117 | +看家 |
| 118 | +吃鱼 |
| 119 | +抓老鼠 |
| 120 | +``` |
| 121 | + |
0 commit comments