多态是同一个对象,在不同时刻表现出来的不同形态的能力。
举个例子:二哈;
我们可以说二哈是狗:Dog erha = new Dog();
我们也可以说二哈是动物:Animal erha = new Animal();
同样这只二哈,在不同的时刻表现出来了不同的形态,这就是多态。
多态的三个必要条件:
怎么理解这三个条件呢,直接上代码:
// 动物类 class Animal { public void eat() { System.out.println("动物吃东西"); } } // 狗狗类(继承了动物类) class Dog extends Animal { // 重写父类eat()方法 @Override public void eat() { System.out.println("狗狗吃骨头"); } } // Demo类 public class PolymorphismDemo { public static void main(String[] args) { // 父类引用指向子类对象 Animal erha = new Dog(); erha.eat(); } }
最后的运行结果是狗狗吃骨头
,三个条件我在注释中也都标注了出来。这就是最基本的一个多态案例。
Animal erha = new Dog(); System.out.println(erha.name); // erha.name只能取到父类Animal中的值
Animal erha = new Dog(); erha.eat(); // erha.eat()调用的是子类Dog重写后的方法
怎么理解这两句话呢,直接上代码:
// 动物类 class Animal { public String name = "动物"; public void eat() { System.out.println("动物吃东西"); } } // 狗狗类 class Dog extends Animal { public String name = "狗狗"; @Override public void eat() { System.out.println("狗狗吃骨头"); } } // Demo类 public class PolymorphismDemo2 { public static void main(String[] args) { Animal erha = new Dog(); System.out.println(erha.name); erha.eat(); } }
最后的运行结果是:
动物 狗狗吃骨头
为什么成员变量和成员方法的访问不一样呢?
因为成员方法有重写,eat()
被子类重写了;而成员变量没有重写,访问的依然是父类的name
。
不能使用子类的特有功能,举个例子
// 动物类 class Animal { public String name = "动物"; public void eat() { System.out.println("动物吃东西"); } } // 狗狗类 class Dog extends Animal { public String name = "狗狗"; public int age = 5; @Override public void eat() { System.out.println("狗狗吃骨头"); } public void bark(){ System.out.println("狗狗汪汪叫"); } } // Demo类 public class PolymorphismDemo3 { public static void main(String[] args) { Animal erha = new Dog(); System.out.println(erha.name); erha.eat(); //System.out.println(erha.age); //ERROR //erha.bark(); //ERROR } }
因为这个erha
是父类引用(Animal)指向子类对象(Dog)所创建出来的,子类的特有功能age
与bark()
这边都没法获取,所以这边两行都会报错。
Animal a = new Dog(); // 向上转型,父类引用指向子类对象 Dog d = (Dog) a; // 向下转型,父类引用被强制转换为子类对象
在代码中实现:
// 动物类 class Animal { public void eat() { System.out.println("动物吃东西"); } } // 狗狗类 class Dog extends Animal { @Override public void eat() { System.out.println("狗狗吃骨头"); } public void bark(){ System.out.println("狗狗汪汪叫"); } } // Demo类 public class PolymorphismDemo4 { public static void main(String[] args) { Animal erha = new Dog(); // 向上转型 erha.eat(); //erha.bark(); //ERROR Dog xiaoha = (Dog) erha; // 向下转型 xiaoha.eat(); xiaoha.bark(); } }
最后的运行结果是:
狗狗吃骨头 狗狗吃骨头 狗狗汪汪叫
在向上转型中,由于是父类引用指向子类对象,因此无法调用bark()
方法,而在向下转型中,父类引用转为子类对象,因此可以调用子类的bark()方法。