- 多态的概念:
同一个对象,在不同时刻的表现出来的不同状态; - 多态的前提:
有继承/实现关系;
有方法重写;
有父类引用指向子类对象;
多态的代码演示
public class DemoPolymorphic {
public static void main(String[] args){
// 父类引用指向子类对象
Animal a = new Cat();
}
}
class Animal {
public void eat(){
System.out.println("动物吃东西");
}
}
class Cat extends Animal {
// 继承和重写
@Override
public void eat(){
System.out.println("猫吃鱼");
}
}
- 多态中成员的访问特点:
成员变量:编译看父类,执行看父类
成员方法:编译看父类,执行看子类
下面通过一段代码分析,解释原因
public class DemoPolymorphic {
public static void main(String[] args){
// 父类引用指向子类对象
Fu f = new Zi();
System.out.println(f.age); // 36;
System.out.println(f.show); // 子类方法被执行
}
}
class Fu {
// 父类属性
private int age = 36;
public void show(){
System.out.println("父类方法被执行");
}
}
class Zi extends Fu {
// 子类属性
private int age = 12;
// 继承和重写
@Override
public void show(){
System.out.println("子类方法被执行");
}
}
原因在于成员方法有被重写,但是成员变量没有
- 多态的利弊:
好处在于提高了代码的扩展性
坏处在于不能使用子类特有的方法
代码演示
public class DemoPolymorphic {
public static void main(String[] args){
useAnimal(new Dog());
useAnimal(new Cat());
}
public static void useAnimal(Animal a){
a.eat();
//a.watch(); // false
}
}
class Animal {
public void eat(){
System.out.println("动物吃东西");
}
}
class Cat extends Animal {
// 继承和重写
@Override
public void eat(){
System.out.println("猫吃鱼");
}
}
class Dog extends Animal {
// 继承和重写
@Override
public void eat(){
System.out.println("狗吃肉");
}
public void watch(){
System.out.println("狗可以看门");
}
}
- 多态的转型
从父类类型转为子类类型
代码演示 - 关键部分
public static void main(String[] args) {
Animal a = new Dog();
Dog dog = (Dog)a;
/*
但是这样一般来说是不严谨的,因为不能直接说动物是狗
如果被转换的引用类型变量,对应的实际类型和目标类型不是
同一类型,那么就会出现ClassCastException:类型转换异常
*/
}
- 多态中转型风险的解决
添加 instanceof 判断条件
代码演示 - 关键部分
public static void main(String[] args) {
useAnimal(new Cat());
useAnimal(new Dog());
}
// 解决ClassCastException
public static void useAnimal(Animal a) {
a.get();
if(a instanceof Dog) {
Dog dog = (Dog)a;
dog.watch(); //true
}
}