多态是面向对象编程(OOP)的核心特性之一,指同一消息(方法调用)作用于不同对象时,可能产生不同的行为。根据 Cardelli 和 Wegner 的分类,多态分为以下四类,进一步划分为通用多态和特定多态:
1. 通用多态(Universal Polymorphism)
适用于广泛类型,强调代码的通用性。
(1) 参数多态(Parametric Polymorphism)
-
定义:代码不依赖具体类型,通过参数化类型实现复用(最纯的多态)。
-
示例:
-
泛型(Generics)(如 Java、C#):
java
复制
List<String> list = new ArrayList<>(); // String 为类型参数
-
模板(Templates)(如 C++):
cpp
复制
template <typename T> T add(T a, T b) { return a + b; }
-
-
特点:同一逻辑适用于任意类型,编译时确定具体类型。
(2) 包含多态(Inclusion Polymorphism)
-
定义:通过子类型化(Subtyping)实现,子类对象可替代父类对象。
-
示例:
java
复制
class Animal { void sound() { ... } } class Dog extends Animal { void sound() { System.out.println("Bark!"); } } Animal a = new Dog(); // 子类实例赋值给父类引用 a.sound(); // 输出 "Bark!"(动态绑定)
-
特点:运行时动态绑定方法(如 Java 的
@Override
)。
2. 特定多态(Ad-hoc Polymorphism)
针对特定场景,行为依赖上下文。
(3) 过载多态(Overloading Polymorphism)
-
定义:同一名称的方法或操作符在不同上下文中有不同含义。
-
示例:
-
方法重载(Java/C++):
java
复制
void print(int x) { ... } void print(String s) { ... } // 同名方法,参数类型不同
-
操作符重载(C++/Python):
python
复制
class Vector: def __add__(self, other): # 重载 "+" 操作符 return Vector(self.x + other.x, self.y + other.y)
-
-
特点:编译时静态绑定,根据参数类型/数量选择方法。
(4) 强制多态(Coercion Polymorphism)
-
定义:编译器或运行时自动将类型转换为符合操作的期望类型。
-
示例:
-
隐式类型转换:
java
复制
int a = 5; double b = a; // int 自动转为 double
-
字符串拼接:
python
复制
print("Age: " + 25) # int 25 被强制转为字符串
-
-
特点:可能引发精度损失或运行时错误(需谨慎使用)。
多态的核心价值
-
代码复用:参数多态和包含多态减少重复代码。
-
灵活性:同一接口支持多种实现(如子类覆盖父类方法)。
-
可扩展性:新增类型无需修改原有逻辑(如通过继承扩展)。
对比总结
类型 | 分类 | 绑定时机 | 典型应用 |
---|---|---|---|
参数多态 | 通用 | 编译时 | 泛型、模板 |
包含多态 | 通用 | 运行时 | 子类方法重写(@Override ) |
过载多态 | 特定 | 编译时 | 方法/操作符重载 |
强制多态 | 特定 | 编译/运行时 | 隐式类型转换 |
实际应用建议
-
优先使用参数多态:如泛型,提高类型安全性和复用性。
-
慎用强制多态:避免隐式转换导致的潜在错误。
-
合理设计继承层次:包含多态需遵循里氏替换原则(LSP)。