多态性是面向对象的第三大重要特征,建立在继承性之上。
多态性一词怎么理解呢?就是一个事物的多种形态的性质。在面向对象中,主要体现为一个父类的属性方法可以继承给多个子类。子类就理解为父类的多种形态。以动物为例,猫和狗都有动物的特征,动物即“父类”,猫和狗就是动物的多个“子类”。
那么多态性有什么用处呢?在代码中,一个子类的对象,引用却是用父类的引用类型,就是多态性。例:
若已创建了Animal类,Dog类和Cat类继承于Animal类。
Animal a1 = new Dog();
这里引用数据类型为Animal类,创建的对象是Dog类。
若此时要调用a1的方法,是怎么运行的呢?
若将光标放到a1调用的jump方法上,显示的是Animal的方法。
再看Animal和Dog中的jump方法。
可以发现,Dog中的jump方法是经过重写的,这时将代码运行:
能发现,虽然编译器指明a1调用的方法是Animal类的jump方法,但是实际运行却是运行的Dog类中的重写后的jump。
在多态的场景下,调用方法时。编译时,认为方法是父类的方法。实际运行时,执行的是子类中的重写方法。(前提:调用的方法的前提是此方法是子类重写了父类的方法的情况下,才满足以上多态性。)
多态性的使用前提:1.要有类的继承关系。2.要有方法的重写。
多态性的适用范围:适用于重写的方法,不适用于属性。
但是,如此也看不出多态性有什么用处。多态性一般也不会直接用父类的引用来创建对象,那并不能体现多态性的优点。具体多态性的使用如下,还是以Animal和Dog和Cat举例。
在adopt的参数列表中,参数animal的引用类型为Animal。在main方法中,创建Dog和Cat的对象dd和cc,再将dd和cc作为参数调用adopt方法。
一个adopt的方法,可以同时供Cat类和Dog类的对象使用,因为参数的引用数据类型声明为Animal,而Cat和Dog是Animal的子类。
如此可以看出,多态性的优点是,可以极大减少代码的冗余,不需要定义多个重载的方法,一个方法可以供多个子类使用。
那么如果想要在adopt中调用Cat和Dog中的特有的方法,该如何做呢?
这时候便要涉及到向下转型。
向下转型即将父类的引用转化为子类的引用。需要使用强转符()。比如,Dog dog = (Dog)animal 。注:这种转换dog和animal的地址相同,指向内存中同一个对象的存储,只是二者的引用数据类型不同。
还涉及到了一个关键字:instanceof,格式:a instance A 。instanceof是用来判断对象a是否是A类型或者A的子类类型的实例。如果是返回true,不是则返回false。
如此,便可以用instanceof来判断传入的参数animal是哪个类的实例,再将animal的引用数据类型向下转型为相应的Animal的子类的引用数据类型之后,就可以调用相应的子类的特有的方法了。
例:
输出结果为: