为图形界面寻找可复用的程序结构

1980年代中期,苹果Macintosh的窗口、菜单和鼠标操作让用户更容易使用电脑,却增加了应用程序的开发工作。程序既要执行自己的计算或绘图任务,又要处理移动窗口、选择菜单和打开文件等共同操作。苹果把这些共同行为组织成可扩展的对象库MacApp,Object Pascal则提供编写和扩充这些对象的语言工具。

这一方案接续了Lisa计算机上的Clascal。苹果的Macintosh软件组与Pascal设计者尼克劳斯·维尔特合作,重新整理这套面向对象扩展。拉里·特斯勒1985年2月14日署的《Object Pascal Report》已明确说明:团队完成了Macintosh编译器实现,并建立了对象库和示例应用。因此,1986年是它进入更多教材与技术讨论的阶段,不能作为设计工作的起点。

参考:[1] [3] [4]

删减概念,而不是不断增加语法

特斯勒的比较备忘录记录了设计取舍。早期名为Clascal 85的方案原打算作较大改动,维尔特认为许多改动不合适。最终设计保留Pascal的类型和过程结构,用object声明对象类型,并在括号中指定它所继承的类型;不继承其他类型时,括号便可省略。

团队取消了抽象方法与默认方法之间的专门分类,也取消特殊的Create方法。程序先分配对象,再调用自己命名的初始化方法。特斯勒把这些变化解释为减少学习概念和实现中的例外。维尔特与丹·英格尔斯还主张,在方法内部访问本对象的成员时,可以省去显式的self前缀。

参考:[3] [1]

对象把数据与可替换的操作放在一起

普通Pascal的记录保存若干字段;Object Pascal的对象还声明方法,也就是作用于该对象的过程或函数。一个后继类型继承原类型的字段和方法,可以增加新成员,也可以用override标明自己的替代实现。这使共同代码能够留在祖先类型中,变化部分才写在后继类型里。

对象在程序运行期间创建和销毁,变量保存的是对象引用,而非整个对象。把一个引用赋给另一个变量,两者可以指向同一个对象,不会自动复制数据。通过引用调用方法时,程序依据对象在运行中的实际类型选择实现;inherited则用于调用被继承的实现,避免再次转入本级的覆盖方法。

参考:[1]

用工资计算看继承如何工作

1985年的语言报告用雇员程序说明这种关系。Employee对象保存姓名、工资率和计薪时数,提供RegularPay和IssuePaycheck等方法。ExemptEmployee继承它,却覆盖RegularPay,使工资按规定的计薪时数计算,而不随传入的实际工作时数改变。Executive又增加每周奖金,并覆盖发薪方法。

假设变量Emp的声明类型是Employee,它仍可引用后两种对象。执行Emp.RegularPay时,运行系统会选择适合实际对象的工资算法。这样,已有的工资处理程序不必逐一询问雇员属于哪一类;以后增加一种雇员类型,也可让同一调用使用新的算法。报告中的例子还让初始化与奖金设置通过方法进行,便于集中维护字段之间的约束。

参考:[1]

Macintosh实现受内存组织制约

语言规范不限定引用的底层形式,苹果的Macintosh实现却使用句柄,即指向另一指针的指针。堆内存整理时,对象本体可以搬到新地址;通过句柄访问,程序仍能找到它。若程序员保存对象的直接地址,随后一次过程调用触发内存搬移,旧地址就可能失效。

同日的实现备忘录专门说明这类风险,也列出编译器与规范的暂时差异。例如,当时对象类型只能在编译单元的接口部分声明,一些override一致性检查尚未完成。可见Object Pascal的规范、编译器当前能力和Macintosh内存管理是三个相互关联的层次,规范中的允许事项未必已全部落实。

参考:[2]

从语言扩展到MacApp开发实践

特斯勒在施穆克1986年著作的序言中说,MacApp自1985年2月已作为Lisa到Macintosh的交叉开发系统提供使用,写序时苹果正在测试Macintosh独立开发版本。书中把应用程序、文档、窗口、框架、视图和命令列为MacApp的六种基本类:开发者继承有关类并覆盖方法,便能把通用程序骨架改成自己的应用。

1986年8月《BYTE》的技术综述已将Object Pascal作为苹果支持的实现介绍,并指出它有意省去类方法、多重继承等复杂机制。苹果还在原始报告中把语言规范贡献给公共领域,鼓励其他Pascal编译器采用兼容扩展。早期Object Pascal的影响,因而同时来自简洁的语言设计、可工作的编译器,以及能够直接解决界面开发问题的对象库。

参考:[4] [5] [1]