1. 引言

根据词典定义,多态性(Polymorphism)是指“以多种形式出现的特性”。由于多态性出现在多个科学领域中,因此这是一个通用定义。在计算机领域,它的定义更贴近我们的理解:

“多态性是一种编程语言特性,允许一个例程在不同时间使用不同类型的变量。”

在本教程中,我们将深入探讨这句话的含义。但在那之前,我们先理解一下我们是如何看待现实世界的。

2. 现实世界中的多态性

人类的大脑会对我们周围的事物进行归纳和分类。我们会寻找它们之间的相似点,并将它们归入不同的类别。这些类别可以是广泛的,例如“动物”,也可以是具体的,例如“黑色的三腿桌子”。

我们将这个过程称为分类,分类的结果就是(Class)。

人类之所以进化出这种能力,是因为它有助于我们做出更快、更准确的决策。比如,一个原始人看到剑齿虎就会逃跑或躲藏,看到兔子则不会。他并没有见过每一只兔子或剑齿虎,但通过观察足够多的例子,他建立了能准确描述这些动物的“类”。

但相似的事物不仅具有相似的属性,它们的行为也可能相似。而这一点正是多态性的强大之处。

以员工为例。从雇主的角度来看,员工最重要的行为就是“工作”。每个员工都清楚自己的职责。至少在理想世界中是这样。

这意味着每天早上,老板只需要告诉员工“开始工作”,他们就会自动去做自己的事情,而不需要老板再一一指导。

如果我们反过来,设想一个老板不依靠员工的自主性,那会是怎样的场景:

  • “你是做什么的?”
  • “我是后端开发。”
  • “那你去创建一个接口,执行一个批处理任务。任务完成后,把结果存到数据库,并通知用户。”

然后转向下一个员工:

  • “你是做什么的?”
  • “我是UX设计师。”
  • “那你去画个线框图,注重可访问性,采用移动优先策略。完成后组织一次焦点小组测试。”

这种做法显然效率极低。我们称之为“微观管理”(micromanagement),幸运的是,这并不是我们理想的工作方式。

对于大型公司来说,这种方式是不可持续的。所以,我们更倾向于让员工自主完成任务,而不是由老板事无巨细地安排。

3. 编程中的多态性

在编程中,多态性通常与面向对象(Object-Oriented, OO)编程相关联。虽然函数式和结构化编程也支持多态机制(如高阶函数或函数指针),但由于面向对象编程是最主流的范式,我们这里也主要讨论它。

回到我们前面的员工例子。在面向对象编程中,我们可以这样建模:

创建一个 Employee 基类,然后有两个子类:BackendDeveloperUxDesigner

employees simple

可以看到,Employee 类中有一个抽象方法 work(),两个子类各自实现了这个方法。

有了这样的结构,我们就可以创建一个 Boss 类,它可以轻松地指挥员工开始工作:

boss employees simple

4. 多态的优势

微观管理之所以存在,是因为控制欲强的老板想掌控一切。但在编程中,我们更倾向于使用多态来解耦类之间的依赖。

当我们想要完全控制另一个类的行为时,我们必须了解它的每一个细节。这对于一两个外部类来说还可以接受,但当系统变大时,这种做法会迅速失控,而且不利于扩展。

假设公司决定扩展业务,开始生产硬件。那老板就得了解电气工程师、机械工程师等新角色的职责。这显然不现实,尤其如果他连现有员工的工作都不完全了解。

在代码层面,这意味着我们要在 Boss 类中实现所有新角色的行为,这很快就会变得难以维护。

而使用多态后,我们只需在 ElectricalEngineerMechanicalEngineer 类中实现各自的 work() 方法:

employees full

之后,我们只需要“雇佣”这些新员工,并将他们添加到 Boss 类的员工列表中即可。

5. 总结

通过这个简单的例子,我们理解了多态的含义:

“多态性是一种编程语言特性,允许一个例程在不同时间使用不同类型的变量。”

一个声明为 Employee 类型的变量可以引用任何 Employee 的子类实例。我们只需要知道的是:他们都具有 work() 的能力。因此,我们只需调用 work() 方法即可。至于具体如何实现,那是运行时根据变量实际持有的对象类型决定的。

我们并不关心他们是怎么完成工作的,因为我们相信每个员工都知道自己该做什么 ✅。这就是多态的核心思想:统一接口,不同实现


原始标题:The General Concept of Polymorphism