一、多态介绍
继承提高了代码的重用性,让类和类之间建立的联系,为多态创造了条件。
1、什么是多态
多态是指序中定义的引用变量所指向的具体类型在编程时并不确定,而是在程序运行期间才确定。
由于在程序运行时才确定具体的类型,即不修改程序的代码就可以改变程序运行时所绑定的具体代码,让程序选择多个运行状态,这就是多态性。
2、多态的种类(主要指运行期)
编译时多态:方法重载,系统在编译时确定调用重载函数的哪个版本
运行时多态:基于面向对象的继承性实现,父类型的引用可以指向子类型的对象,这就是向上转型。通过一个父类的引用发出的方法调用,执行的方法可能是在父类中的实现,也可能是在子类中的实现,这由运行时刻具体的对象类型决定。
3、向上转型
首先理解,子类是父类的特殊化,每个子类是其父类的实例。
所以在允许的继承关系中,可以将子类对象赋值给父类型的引用。
反过来,会导致编译时错误。
并且,通过这个引用访问子类的对象时,只能访问父类中拥有的方法和属性。因为编译器认为引用是父类中的引用。
/*Bicycle是MountainBike的父类*/ Bicycle myBike=new MountainBike(); /*Object是所有类的父类*/ Object obj=new MountainBike();
4、向下转型
即把上转型中的父类型引用又赋值给一个子类型的引用,指向的仍然是这个子类型的对象。
必须是显示的,即强制类型转换。
Object obj=new MountainBike(); MountainBike myBike=(MountainBike) obj;
这一转换编译器会通过,但是如果在运行时obj不是MountainBike类型,会抛出异常。
所以在这种情况下,为了比卖你运行时异常,我们可以使用instanceof操作符做逻辑测试:
if(obj instanceof MountainBike){ MountainBike myBike=(MountainBike obj); }
在一个深层次的继承关系中,这种判断分支是一个噩梦。因而在设计良好的程序中,应该尽量避免这种判断!
5、方法重写(override)
(父类子类同名方法的参数个数、类型与顺序必须保持一致)
返回类型必须兼容,比如父类中的类型为某个类的对象,子类中的方法可以返回这个类或者它的子类。
父类的静态方法不能被子类重写为非静态;
父类的非静态方法不能被子类重写为静态。
二、多态的实现
子类继承父类后,父类型的引用变量既可以指向父类对象,也可以指向子类对象。
当相同的消息发给一个对象引用时,该引用会根据具体指向子类还是父类对象而执行不同的行为。多态性就是相同的消息使得不同的对象作出不同的响应的机制。
1、继承实现多态
继承实现多态有三个条件:继承关系、方法重写和向上转型(子类的引用复制父类的对象引用)。
只有满足了3个条件,才能在一个继承结构中使用统一的逻辑代码处理不同的对象,从而达到执行不同的动作的目的。
(具体执行父类对象还是子类对象的方法,你看指向的内存是哪个的实例就好了)
2、关于equals()方法
操作符“==”可以比较两个基本类型的变量是否相等。
当我们使用它比较两个对象的引用变量,实际上实在比较两个引用变量是否指向了相同的对象。这里,相同的对象是指在堆中占用同一块内存单元中的同类型对象。
如何比较两个对象的引用变量所指向的对象的内容是否相同?
使用equals()方法(Object类中定义了,意味着每个类都会有这个方法),返回boolean。
但是默认情况下,它比较的是对象的引用是否相同。
String、Integer、Date中,equals()方法被重写了,比较的不是内存中的地址而是对象的内容。
在自定义的类的对象中,equals()比较两个引用是否指向了同一个对象。因此,如果想比较对象的内容,在类中重写equals()吧!