Alan Kay 2003年解读面向对象编程的本质含义
速览
本文回顾了 Alan Kay 在2003年对面向对象编程(OOP)概念的深度解读。他澄清了 OOP 并非仅仅关于消息传递或数据封装,而是更广泛的计算哲学。这一观点对于理解现代软件架构设计具有重要参考价值。
AI 深度解读
Alan Kay 论“面向对象编程”的本义(2003)
背景
这组邮件记录了 Alan Kay 博士与 Stefan Ram 在 2003 年 7 月的通信。Stefan Ram 正在编写关于“面向对象编程”(Object-Oriented Programming, OOP)的教程页面,他需要权威的定义来源。他认为仅有的两个权威来源是国际标准化组织(ISO,定义见于 ISO/IEC 2382-15)以及该术语的创造者 Alan Kay。
尽管业界常将“继承、多态、封装”视为 OOP 的核心,但这些并非第一手资料。Stefan Ram 希望 Alan Kay 澄清“面向对象”一词最初的含义、首次使用的时间地点,以及他对这一概念最本质的理解。Alan Kay 在回复中详细阐述了他当年构思该术语时的原始思想,指出后世对 OOP 的理解发生了严重的偏离。
核心内容
1. 术语的起源与初衷
Alan Kay 确认“面向对象”一词确实由他创造。大约在 1967 年(具体为 1966 年 11 月之后),受 Ivan Sutherland 的 Sketchpad、Simula、ARPANet 的设计、Burroughs B5000 计算机架构,以及他自身的生物学和数学背景影响,他构想出了一种新的编程架构。当有人问他正在做什么时,他回答:“这是面向对象编程。”
2. 原始构想的核心要素
Kay 指出,OOP 的原始概念包含以下几个关键部分,这与后来被广泛接受的定义大相径庭:
-
消息传递(Messaging)是核心: 对象被类比为生物细胞或网络中的独立计算机。它们之间唯一的交互方式是消息传递。这一理念在最初就已确立,尽管后来花费了很长时间才在编程语言中实现高效的消息传递机制。
-
“消除数据”(Getting rid of data): Kay 希望彻底消除传统意义上的“数据”。受 Burroughs B5000 近乎不可思议的硬件架构启发,他意识到“细胞/整台计算机”的隐喻可以消除数据。在这种视角下,数据不再是独立的实体,而是消息令牌(message token)。这与他早期的数学背景有关,他最初将这些符号视为函数和过程的名称。
-
泛型性(Genericity)而非多态(Polymorphism): 数学背景让他意识到每个对象可以关联多种代数结构,且存在家族式的代数结构,这极具价值。
- 关于多态:术语“多态”是后来由 Peter Wegner 强加的,Kay 认为这个词并不准确,因为它源于函数的命名法,而他想要的远不止函数层面的多态。
- 关于泛型:他创造了“泛型性”(genericity)一词,用于处理准代数形式的泛型行为。
-
摒弃继承(Inheritance)作为内置特性: 尽管他高度推崇 Ole-Johan Dahl 和 Kristen Nygaard(Simula 的创造者),但他不喜欢 Simula I 或 Simula 67 中继承的实现方式。因此,在最初的设计中,他决定不将继承作为内置特性,直到他更好地理解它。
3. 技术演进路径
- 早期实验:Kay 使用改编自 van Wijngaarten 和 Wirth 的“Algol 泛化”以及 Wirth 的 Euler 语言进行实验。这些语言具有 LISP 般的特性,但拥有更传统的可读语法。
- 对 LISP 的理解:起初他不理解 LISP 中“元语言实体化”的复杂概念,但通过 Irons 的 IMP 等来源,他发展出了关于可扩展语言的思想。
- 第二阶段:在深入理解 LISP 后,他利用这些理解构建了更优雅、更小、更强大且支持晚期绑定的底层结构。Dave Fisher 的论文(采用 McCarthy 风格)关于可扩展控制结构的想法提供了极大帮助。此外,Carl Hewitt 的 PLANNER 也是重要影响源,它比 Prolog 更早地预示了许多特性。
- Smalltalk 的诞生与偏离:Xerox PARC 的原始 Smalltalk 源于上述思想。但后续的 Smalltalk 版本被批评“倒退”回了 Simula 的模式,并未用更安全且同样有用的扩展机制来替代原有的机制。
4. OOP 的本质定义
针对 Stefan Ram 的请求,Alan Kay 给出了他对 OOP 最简洁、最本质的定义:
OOP 对我来说,仅意味着:消息传递、状态-过程(state-process)的本地保留与保护/隐藏,以及所有事物的极端晚期绑定(extreme late-binding)。
他认为这种范式可以在 Smalltalk 和 LISP 中实现。
5. 历史回顾与两条路径
在第二封邮件中,Kay 补充了关于 Simula 引发的两条主要发展路径:
- 生物/网络非数据过程路径(Kay 的路径):这是早期偶然形成的路径,强调对象作为非数据的实体,通过消息交互。
- 抽象数据类型(ADT)路径:这是后来成为研究对象的另一条路径,强调数据与过程的结合。
Kay 指出,计算机科学界主流选择了 ADT 路径,并坚持“数据-过程”范式。然而,历史上许多先驱工作都指向了“对象作为非数据”的理念,包括:
- USAF Burroughs 220 文件系统。
- MIT 的 Doug Ross 早期工作(在数据结构中嵌入过程指针)。
- Sketchpad(具有完整的泛型性/多态性)。
- Burroughs B5000(其程序引用表是真正的“大对象”,包含数据和过程指针,且能智能处理指向错误)。
- Bob Balzer 的《Dataless Programming》(无数据编程)。
- John Reynolds 的《Gedanken》(1970),证明正确使用 lambda 表达式可以通过过程抽象数据。
Kay 提到,像他、Carl Hewitt、Dave Reed 等人组成的群体(主要来自 ARPA 社区,参与 ARPANet 设计)认为计算的基本单位是整台计算机。然而,整个 70 年代和 80 年代,许多人顽固地试图用“远程过程调用”(RPC)来替代对象和消息的概念。Kay 感叹道:“Sic transit gloria mundi”(世间的荣耀转瞬即逝)。
关键要点
- OOP 不等于“继承、多态、封装”:这是后世对 OOP 的误解或简化。Alan Kay 明确表示,他最初的设计中甚至去掉了继承。
- 核心三要素:
- 消息传递(Messaging):对象间唯一的交互方式。
- 状态-过程的本地保留与隐藏(Local retention and protection/hiding of state-process):对象拥有并保护其内部状态和处理逻辑。
- 极端晚期绑定(Extreme late-binding):所有绑定都推迟到运行时进行。
- “消除数据”的理念:在 Kay 的原始构想中,数据不应是独立的实体,而应被视为消息令牌。对象更像是一个独立的计算单元(如生物细胞或网络节点),而非数据的容器。
- 泛型性(Genericity)优于多态(Polymorphism):Kay 认为“多态”一词源于函数命名法,局限了思想;他更倾向于使用“泛型性”来描述对象处理多种代数行为的能力。
- 历史偏离:计算机科学界主流选择了基于抽象数据类型(ADT)的“数据-过程”范式,而忽略了 Kay 等人提出的基于消息和非数据对象的“生物/网络”范式。
- 先驱工作的忽视:Sketchpad、Burroughs B5000、PLANNER 等早期系统实际上已经实现了类似 OOP 的特性(如泛型性、过程与数据的统一),但未被充分认可。
意义与影响
这组邮件对于理解软件工程的历史和面向对象编程的本质具有极高的价值:
- 正本清源:它纠正了业界长期以来将 OOP 等同于“继承、多态、封装”的
