知识卡片

多态本质是函数指针的安全化,催生了插件式架构

普通读书笔记卡

内容

[[封装与继承并非面向对象编程独有的能力]]分析到多态时结论不同——多态同样不是OOP的理论创新(自冯·诺依曼架构诞生起程序员就靠函数指针模拟多态:UNIX强制每个IO设备驱动实现open/close/read/write/seek五个标准函数,getchar()本质就是调用STDIN指向的FILE结构体里的函数指针,这套机制和C++虚函数表vtable的原理完全一致),但OOP语言确实让多态变得更安全、更易用了——用函数指针显式实现多态依赖程序员人工遵守一系列约定(初始化顺序、调用方式),一旦有人违反,就会产生极难追踪的bug,而OOP语言从语言层面消除了人工遵守这些约定的必要。这个”安全化”带来的直接后果是插件式架构变得可行:copy程序要支持新的IO设备(比如手写识别设备到语音合成设备),完全不需要修改甚至重新编译,因为copy程序的源代码根本不依赖具体设备驱动代码,只要驱动实现了标准函数就能被插上使用——IO设备变成了copy程序的插件。这背后是一条从1950年代末就开始积累的经验:程序应该与设备无关(早年程序依赖打孔卡片,客户改用磁带后大批程序要重写,这个教训催生了”程序应与具体设备解耦”的诉求)。函数指针虽然理论上早就能做到这点,但太危险,大部分程序员不敢在自己程序里引入这种插件特性;面向对象编程的出现,才让插件式架构可以在任何地方被安全地大规模使用。

参考来源

- 位置:《架构整洁之道》第5章《面向对象编程》"多态""多态的强大性"(源文件:_epub-src/text/part0011_split_003.html) - 结论依据:原文用UNIX标准IO函数与FILE结构体函数指针实现getchar多态、C++虚函数表原理相同的例子说明多态本质是函数指针应用,并指出OOP语言消除了人工遵守函数指针约定的危险性,用copy程序无需修改即可支持新IO设备说明插件式架构由此变得可行,直接支撑本卡片结论。 - 原始内容:归根结底,多态其实不过就是函数指针的一种应用……面向对象编程语言为我们消除了人工遵守这些约定的必要,也就等于消除了这方面的危险性……IO设备变成了copy程序的插件。