特设多态

特设多态ad hoc polymorphism)是程式设计语言的一种多态,多态函数有多个不同的实现,依赖于其实参而调用相应版本的函数。因此,特设多态仅支持有限数量的不同类型。函数重载乃至运算符重载也是特设多态的一种。

概述

特设多态与参数多态相对。ad hoc在这里并不是贬义,而是指这类多态并不是类型系统的基本特性,不是像参数多态那样适用于无穷多的类型,而是针对特定问题的解决方案。

换言之,参数多态对各模板参数的实现,是根据模板的通用(generically)的行为的抽象,即泛型的语义;而特设多态可以针对不同的版本实现完全不同的行为,或曰对于每个不同的模版参数都有单独的版本来应对。打个比方:假如我们要把原材料切成两半——

  • 参数多态:只要能“切”,就用工具来切割它;
  • 特设多态:根据原材料是铁还是木头还是什么来选择不同的工具来切。

历史

特设多态的名字来源于其发明人克里斯托弗·斯特雷奇于1967年8月在哥本哈根的电脑程式设计暑期学校发表的著名论文《编程语言中的基础概念英语Fundamental Concepts in Programming Languages》,该文首次提出了参数多态、特设多态、左值右值等概念。[1]

早绑定

多态的早绑定(early binding)是在编译期,编译器完成多态的分派机制:把多态函数、多态类型的名字根据模板参数绑定到具体的模板实现。

晚绑定

多态的晚绑定英语Late binding是在运行期,程序确定即将要调用的多态函数的实现。Smalltalk实现了这种晚绑定机制。

例子

加法运算符+假设可以运用到如下的情形:

  1. 1 + 2 = 3
  2. 3.14 + 0.0015 = 3.1415
  3. 1 + 3.7 = 4.7
  4. [1, 2, 3] + [4, 5, 6] = [1, 2, 3, 4, 5, 6]
  5. [true, false] + [false, true] = [true, false, false, true]
  6. "bab" + "oon" = "baboon"

重载

为此,需要的重载实现:

  • 第一种情形,需要整型加法;
  • 第二、第三种情形,需要浮点型加法。其中第三种情形需要隐式类型转换(type coercion)。
  • 第四、第五种情形,需要list连接操作;
  • 第六种情形,需要字符串字面量英语literal string的连接操作。

因此,运算符名字+实际上使用了三到四种完全不同的函数实现。

参考文献

  1. ^ C. Strachey, Fundamental concepts in programming languages. Lecture notes for International Summer School in Computer Programming, Copenhagen, August 1967