一直对面向对象中的多态模模糊糊,学了忘,忘了学。这次深入学习java,在此记录下,便于以后复习。
多态是面向对象编程语言中,与封装、继承并列为面向对象的三大特征。多态简单来说就是对象在编程时不确定具体的类型,而在运行时候才确定具体类型。
最简单的举例就是animal、cat、dog的故事。
定义animal父类如下:
1 | public class Animal { |
定于Dog类如下:
1 | public class Dog extends Animal{ |
定义Cat类如下:
1 | public class Cat extends Animal{ |
最后调用几个类的代码如下:
1 | public class Test { |
我们定义了两个Animal类型的animal
和animal1
。分别指向Dog和Cat的类实例。由于Cat和Dog均是继承于Animal类的,所以该处会进行向上转型,会丢掉子类自己定义的方法,只能调用定义类型的父类中的方法。
所以定义的animal1实例,虽然指向Cat类的实例,但是由于向上转型,所以无法调用自己定义的重载带有参数的public void shout(String sound)
方法。
而animal实例指向的是Dog类型,Dog类型中重写了父类的shout无参的方法,所以根据java的多态特性,可以在运行时确定对象的类型,所以animal实例能够指向自身的shout类,打印出dog wang wang wang
。
所以对于多态可以有如下的总结:
向上转型的子类的实例对象,无法调用由于向上转型而丢失的子类方法。但是根据多态的特性,能够在运行时,调用子类中对于父类进行重写的方法。也就是能够在运行时确定调用的具体方法。
所以实现多态必须包含三个条件:继承、重写、向上转型。
经典案例
A类:
1 | public class A { |
B类:
1 | public class B extends A{ |
C类:
1 | public class C extends B{ |
D类:
1 | public class D extends B{ |
Test类:
1 | public class Test { |
在看java多态的代码的时候,记住一个点,基类类型的对象,能够调用的方法包括基类本身的方法以及子类中重写的基类的方法。
对于以上代码的解释如下:
a1.show(b)
:b的类型是b,所以对象b在a1调用的show方法上会发生向上转型,b的基类是A,所以只能调用A类中的show(A obj)
方法。a1.show(c)
:c的类型是c,所以这里也一样会发生向上转型,调用A类中的show(A obj)
方法。a1.show(d)
:因为A类中直接定义了show(D obj)
方法,所以直接调用。a2.show(b)
:a2的调用会发生多态。a2的show方法包含基类的show方法和B类型中重写的show(A obj)
方法。所以a2的show一共有三个方法可以进行调用。a2.show(b)
在这三种方法中没有对应的方法,所以b对象会发生向上转型,同时发生多态动态调用重写的方法。最后调用的是B类中的show(A obj)
a2.show(c)
:该处c同样会发生向上转型以及多态,最后调用的仍然是B类中的show(A obj)
a2.show(d)
:因为在基类A中直接定义了show(D obj)的方法,因此直接调用该方法。b.show(b)
:b对象调用的方法包含基类A和本身B类的所有方法。所以该处直接调用show(B obj)
方法b.show(c)
:A和B类中均无对应的方法,所以c会发生向上转型,匹配到show(B obj)
方法b.show(d)
:A类中直接有对应的方法,直接调用show(D obj)
以上便是本次总结的关于java多态的相关知识,更多的知识可以参考《java编程思想》进一步学习。