Part 4 多态
约 796 字大约 3 分钟
2025-04-24
多态是指在面向对象编程中,同一个类的对象在不同情况下表现出来的不同行为和状态。
例如,黑白打印机和彩色打印机都属于打印机Printer
类,但是它们打印效果是不同的。
1 多态的实现
要实现多态,需要三个必要条件:
- 子类继承父类;
- 子类重写父类方法;
- 父类引用指向子类对象。
我们先设计一个Printer
类,这个类定义了所有打印机对象的共同行为接口:都可以“打印”。:
public class Printer {
public void print() {
System.out.println("Printer");
}
}
接着为其继承出两个子类,黑白打印机LegacyPrinter
和彩色打印机ColorPrinter
:
public class LegacyPrinter extends Printer {
@Override
public void print() {
System.out.println("这是一台黑白打印机");
}
}
public class ColorPrinter extends Printer {
@Override
public void print() {
System.out.println("这是一台彩色打印机");
}
}
接下来我们想,黑白打印机和彩色打印机都属于Printer
类,那么能否使用Printer
来声明呢?
是可以的。
public class Main {
public static void main(String[] args) {
Printer legacyPrinter = new LegacyPrinter();
Printer colorPrinter = new ColorPrinter();
legacyPrinter.print(); // 这是一台黑白打印机
colorPrinter.print(); // 这是一台彩色打印机
}
}
尽管legacyPrinter
和colorPrinter
的静态类型是Printer
,但它们实际引用的对象是LegacyPrinter
和ColorPrinter
。当我们调用print()
方法时,Java 会在运行时动态决定调用哪个子类的方法,这就叫做运行时多态。
2 转型和instanceof
关键字
在Printer legacyPrinter = new LegacyPrinter();
中,实际上涉及到了类型转换。按照转换方向的不同,可以分为向上转型和向下转型。
2.1 向上转型
我们刚才做的就属于向上转型。在Printer legacyPrinter = new LegacyPrinter();
中,我们把LegacyPrinter
类型的对象转换为了Printer
类型的对象。
需要强调的是,尽管legacyPrinter
是Printer
类型,但在运行时调用的仍然是LegacyPrinter
的方法,这就是多态。
向上转型便于使用统一的结构(父类)来操作不同的子类,简化代码。
而且得益于同一个静态类型,我们可以把不同的打印机放进同一个Printer[]
数组中统一处理。
public class Main {
public static void main(String[] args) {
Printer legacyPrinter = new LegacyPrinter();
Printer colorPrinter = new ColorPrinter();
Printer[] printers = {legacyPrinter, colorPrinter}; // 编译通过
}
}
2.2 向下转型
向下转型刚好相反,是将父类类型转换为子类类型。
向下转型时需要使用强制类型转换。
public class Main {
public static void main(String[] args) {
Printer printer = new ColorPrinter();
ColorPrinter cp = (ColorPrinter) printer;
cp.print(); // 这是一台彩色打印机
}
}
向下转型的对象一定要符合子类的类型。如果我们把一个实际为LegacyPrinter
类型、声明为Printer
类型的对象,强制转型为ColorPrinter
类型,则会报错:
public class Main {
public static void main(String[] args) {
Printer printer = new LegacyPrinter();
ColorPrinter lp = (ColorPrinter) printer; // Runtime ERROR: LegacyPrinter cannot be cast to ColorPrinter
lp.print();
}
}
2.3 instanceof
关键字
在进行向下转型前,为了避免类型不一致的问题,推荐使用instanceof
关键字做判断:
Printer printer = new LegacyPrinter();
if (printer instanceof LegacyPrinter) {
LegacyPrinter lp = (LegacyPrinter) printer;
lp.print(); // 编译通过,运行时安全调用
}