8月更文挑战第 31天 | Java入门 15

76 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第31天,点击查看活动详情

多态

封装和继承的学习已告一段落,接下来要学习面向对象设计与开发中比较难理解的一个概念—多态。

多态是同一个行为具有多个不同表现形式或形态的能力。

多态性是对象多种表现形式的体现。

比如我们说"宠物"这个对象,它就有很多不同的表达或实现,比如有小猫、小狗、蜥蜴等等。那么我到宠物店说"请给我一只宠物",服务员给我小猫、小狗或者蜥蜴都可以,我们就说"宠物"这个对象就具备多态性。

在汉语中经常存在着“一词多义”的情景。例如“打”这个字是什么意思呢?“打篮球”、“打水”、“打架”中“打”的含义各不相同,因此要想确定某个具体的“打”字的含义,就必须将“打”放入具体的语境,通过上下文来断定。类似的,在程序开发中也存在着类似于这种“一词多义”的特征——多态。

多态可以优雅的解决程序中的扩展性问题。假设在租车系统中有一个 drive(Car car)方法,显然该方法只能传递一个 Car 类型的参数,因此如果想传递一个 Truck 类型的参数,就必须再重新编写一个 drive(Truck truck)方法。后续,随着项目的扩大,如果要给 drive()方法传递十种类型的参数,就需要根据参数类型编写十个重载的 drive()方法。但如果使用多态,这一问题就可以得到很好的解决。

根据继承的知识,可以给 Car 和 Truck 等各种类型的车设置一个共同的父类 Vehicle,之后只需要编写一个 drive(Vehicle vehicle)方法,就可以接收所有子类型的参数了,即可以使用 Vehicle 接收 Car、Truck 等各种子类型变量。实际上,Java 就是通过多态机制实现这一功能的。

在逻辑上,多态与继承类似,都符合is a的关系,例如Car is a Vehicle 、Truck is a Vehicle 等。显然,is a的左侧是子类,而右侧是父类。这种is a的逻辑,就保证了在形式上,父类引用可以指向子类对象,例如Vehicle vehicle = new Car();就是多态的一种典型写法。

Vehicle vehicle = new Car();中,子类的 Car 对象赋值给了父类 Vehicle 引用,这称为向上转型;在引用 vehicle 上调用方法,在运行时刻究竟调用的是父类 Vehicle 中的方法还是子类 Car 中的方法呢?实际需要通过运行时的对象类型来判断,这称为动态绑定。向上转型和动态绑定就是多态的具体实现机制。