1、什么是多态?
具有表现多种形态能力的特征。或者是同一个实现接口,使用不同的实例而执行不同的操作。
使用多态有什么优点?
提高代码的可维护性和可扩展性
子类到父类的转换(向上转型)
Dog dog = new Dog("欧欧","雪娜瑞"); //不涉及类型转换
dog.eat();
Pet pet = new Dog("欧欧","雪娜瑞"); //子类到父类的转换
pet.eat(); //会调用Dog类重写的eat()方法,而不是pet类的eat()方法
pet.catchingFlyDisc(); //编译错误,父类无法调用子类特有的方法
子类转换成父类时的规则:
- 将一个父类的引用指向子类的对象,称为向上转型(upcasting),自动进行类型转换。
- 此时通过父类引用变量调用的方法是子类覆盖或继承父类的方法,不是父类的方法。
- 此时通过父类引用变量无法调用子类特有的方法。
使用父类作为方法的形参实现多态
通常来说,以父类作为方法的形参,子类作为方法的实参。
public void feed(Pet pet){ //Pet父类作为形参
pet.eat(); //调用方法
}
实现多态的三个条件:
- 继承的存在(继承是多态的基础,没有继承就没有多态)。
- 子类重写父类的方法(多态下调用子类重写后的方法)。
- 父类引用变量指向子类对象(子类到父类的类型转换(向上转型))。
父类到子类的转换(向下转型)
当需要调用子类特有的方法时,可以通过将父类再转换为子类来实现。
public clsaa TestPoly{
public static void main(String[] args){
Pet pet = new Dog("欧欧","雪娜瑞");//向上转型
pet.eat();
Dog dog = (Dog)pet; //向下转型,强制类型转换,可调用子类特有方法
Penguin pen=(Penguin)pet; //此时将出现类型转换异常ClassCasException,为什么呢?因为最开始时Pet父类的引用指向的是子类Dog的对象,此时却将Dog对象转换成企鹅对象,肯定会报错。那么如何避免呢?请了解instanceof运算符。
}
}
instanceof运算符
该运算符用来判断一个对象是否属于一个类或者实现了一个接口,结果为true和false。在强制类型转换之前通过instanceof运算符检查对象的真实类型,再进行相应的强制类型转换,这样就可以避免类型转换异常,从而提高代码的健壮性。
示例:
public static void main(String[] args){
Pet pet = new Penguin("楠楠","Q妹"); //向上转换
pet.eat(); //调用方法
if(pet instanceof Dog){ //判断父类引用pet是否属于子类Dog
Dog dog = (Dog)pet; //如果为true,则强制转换
dog.catchingFlyDisc();//可以调用子类特有方法
}else if(pet instanceof Penguin){
Pengin pen =(Penguin)pet;
pen.swimming();
}
}
注意:
- 使用instanceof运算符时,对象的类型必须和instanceof的第二个参数所执行的类或接口在继承树上有上下级关系,否则会出现编译错误。例如 pet instanceof String会出现编译错误。
- instanceof通常和强制类型转换结合使用。