最近学习了多态的概念和使用,在此记录学习一下。
首先,什么是多态?
多态是指:同一个方法被调用,会因为调用对象的不同导致完全不同的行为。
说的有点抽象。先了解一下多态的三要素:继承、重写和父类引用指向子类对象
1. 多态是指 方法是多态,不是属性的多态
2. 多态的存在要有三个条件:继承、重写和父类引用指向子类对象
3. 父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了
继承和重写比较好理解,那什么叫做父类引用指向子类对象?这么抽象的描述怎么理解?
举例来说:
首先实现类的继承和方法重写
public class Animal{
public void shout() {
System.out.println("动物叫");
}
}
class Cat extends Animal{
public void shout() {
System.out.println("猫叫");
}
}
然后进行打印测试
/**
*定义一个Test类
**/
public class Test {
public static void main(String[] args) {
//正常的实例化
Animal a = new Animal();
animalCry(a);
//这就发生了多态,因为有了继承、重写和父类引用指向子类对象Animal a = new Dog();
Dog d = new Dog();
animalCry(d);//狗叫
animalCry(new Cat());//猫叫
}
static void animalCry(Animal a) { //相当于进行了实例化Animal a = new Dog()/Animal a = new Cat()
a.shout(); //因为传的对象不一样,所以调用的方法也不一样
}
}
Animal a = new Dog()或者Animal a = new Cat()就叫做父类引用"Animal a "指向了子类对象 “new Dog()”。
其实只要记住一点,在实际运行是时候是看的“=”右边的是谁。左边只是在给a 贴了一个Animal的标签而已,但是本质上还是Dog或者Cat。
所以依次会打印出:动物叫、狗叫、猫叫
多态的使用是比较常见的,在另外一个特别重要的概念“回调”中也会用到。后续再来补充。
补充一下
其实与多态密切相关的一个概念还有向上转型和向下转型
还是拿上面的代码举例:
父类引用指向子类对象其实是向上转型:
//向上转型,编译器认为a是Animal,执行起来还是以Dog执行
Animal a = new Dog();
向下转型:
//假如直接将a赋值给d,编译器不会通过,需要强制转型
Dog d = a;
Dog d = (Dog)a;
强制转型时要注意可能会出现错误(虽然编译不会报错),什么意思呢?
现在给Dog 类中添加一个新的方法:
class Dog extends Animal{
public void shout() {
System.out.println("狗叫");
}
public void fly(){
System.out.println("狗会飞");
}
}
再加入一个向上转型:Animal c = new Cat();
把c强制转成Dog类:
//在编译的时候d2中有fly()这个方法,但是在执行的时候没有这个方法,会报错!
Dog d2 = (Dog)c;