多态
利用多态可以使程序具有良好的扩展性,并可以对所有类对象进行通用的处理。在7.3节中已经学习过子类对象可以被作为父类的对象实例使用,这种将子类对象视为父类对象的做法称为 “向上转型”。
假如现在要编写一个绘制图形的方法 draw(),如果传入正方形对象就绘制正方形,如果传入圆形对象就绘制圆形,这种场景可以使用重载来实现,定义如下:
public void draw(Square s) { // 绘制正方形的方法
}
public void draw(Circular c) { // 绘制圆形的方法
}
但是这种写法有个问题:正方形和圆形都是图形,这场景细分的重载方式不仅增加了代码量,还降低了 “易用度”。如果定义一个图形类,让它处理所有继承该类的对象,根据 “向上转型” 原则可以使每个继承图形类的对象作为 draw() 方法的参数,然后在 draw() 方法中做一些限定就可以根据不同图形类对象绘制相应的图形。这样处理能够很好地解决代码冗余问题,同时程序也易于维护。
【例7.12】万能的绘图方法(实例位置:资源包\TM\sl\7\12)
创建 Shape 图形类,作为 Square 正方形类和 Circular 圆形类的父类。创建 Demo6 类,并在该类中创建一个绘图用的 draw() 方法,参数为 Shape 类型,任何 Shape 类的子类对象都可以被作为方法的参数,并且方法会根据参数的类型绘制相应的图形。
class Shape { } // 图形类
class Square extends Shape { } // 正方形类继承图形类
class Circular extends Shape { } // 圆形类继承图形类
public class Demo6 {
public static void draw(Shape s) { // 绘制方法
if (s instanceof Square) { // 如果是正方形
System.out.println("绘制正方形");
} else if (s instanceof Circular) { // 如果是圆形
System.out.println("绘制圆形");
} else { // 如果是其他类型
System.out.println("绘制父类图形");
}
}
public static void main(String[] args) {
draw(new Shape());
draw(new Square());
draw(new Circular());
}
}
运行结果如下:
绘制父类图形
绘制正方形
绘制圆形
从本实例的运行结果中可以看出,以不同类对象为参数调用 draw() 方法,可以处理不同的图形绘制问题。使用多态节省了开发和维护时间,因为程序员无须在所有的子类中定义执行相同功能的方法,避免了大量重复代码的编写。同时,只要实例化一个继承父类的子类对象,即可调用相应的方法,如果需求发生了变更,只需要维护一个 draw() 方法即可。
编程训练(答案位置:资源包\TM\sl\7\编程训练)
【训练13】教师与学生 使用多态编写一个程序,在控制台上输出如下内容。其中,人类(People)既是教师类(Teacher)的父类,也是学生类(Student)的父类。
每个人都要工作
教师要认真授课
学生要好好学习
【训练14】交通灯亮几秒? 使用instanceof关键字模拟交通红绿灯的点亮时间,控制台输出如下内容:
红灯亮45秒
黄灯亮5秒
绿灯亮30秒