Java面向对象的3个基本特征:封装,继承和多态
什么是多态?
《Java核心技术》中的定义:一个对象变量可以指示多种实际类型的现象称为多态(ploymorphism)。
那么这个对象变量具体指示的是哪种实际类型,调用的是哪个方法呢?这要在程序运行时才能确认。
举一个多态的例子:
public class DemoClass{
Animal dog = new Dog();
Animal cat = new Cat();
}
class Animal{
public void eat(){};
public void speek(){};
}
class Dog extends Animal{
public void eat(){
System.out.println("吃骨头");
}
public void speek(){
System.out.println("汪汪汪");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("吃鱼");
}
public void speek(){
System.out.println("喵喵喵");
}
}
dog这个对象变量,即可以指示一个Dog实例,也可以指示一个Animal实例,还可以用它指示一个Cat实例,假如我们调用dog.eat()方法,输出的是“吃骨头”,还是“喵喵喵”,还是没有输出,这将由程序在运行时动态确定。
使用多态的好处?
- 体现了“面向抽象编程,而不是面向实现编程”的原则:基于一个抽象的Animal类,我们可以实现任意多种动物,而每种动物的具体习性可以各不相同
- 让程序变得易于扩展:新增一种动物不会影响现有的动物,使用现有的动物调用的eat()和speek()代码不需要改动
超类转子类
在上面的例子中,如果我们这样定义dog将报错:
Dog dog = new Animal();
原因是我们把一个超类的引用赋给了一个子类变量,如果这个子类中比超类多定义了新的属性和方法,那么这时dog如何去调用这些新内容呢?因此Java不允许直接这样赋值。
如果要将一个超类的引用赋给一个子类变量,就需要进行强制类型转换:
Dog dog = (Dog) new Animal();
在强制类型转换之前,最好先用instanceof进行检查:
Animal animal = new Dog();
if(animal instanceof Dog){
Dog dog = (Dog)animal;
}
动态绑定
上面提到了,一个对象变量具体指示的是哪种实际类型,调用的是哪个方法,要在程序运行时才能确认。背后的原理是Java的动态绑定机制,可以参考这篇文章:Java静态绑定与动态绑定_zhangjk1993的博客-CSDN博客