在消息传递模型里,
- 对象有属性,
- 并回应消息,
- 并从其父类继承属性与方法。
当然了,我们知道 CLOS 使用的是通用函数模型。但本章我们只对于写一个迷你的对象系统 (minimal object system)感兴趣,而不是一个可与 CLOS 匹敌的系统,所以我们将使用消息传递模型。
我们已经在 Lisp 里看过许多保存属性集合的方法。一种可能的方法是使用哈希表来代表对象,并将属性作为哈希表的条目保存。接着可以通过 来存取每个属性:
(funcall (gethash 'move obj) obj 10)
我们可以在这个概念上,定义一个 Smalltalk 风格的消息传递语法,
所以想要一个对象 obj
移动 10 单位,我们可以说:
事实上,纯 Lisp 唯一缺少的原料是继承。我们可以通过定义一个递归版本的 gethash
来实现一个简单版,如图 17.1 。现在仅用共 8 行代码,便实现了面向对象编程的 3 个基本元素。
让我们用这段代码,来试试本来的例子。我们创建两个对象,其中一个对象是另一个的子类:
> (setf circle-class (make-hash-table)
(gethash :parent our-circle) circle-class
(gethash 'radius our-circle) 2)
circle-class
对象会持有给所有圆形使用的 area
方法。它是接受一个参数的函数,该参数为传来原始消息的对象:
现在当我们询问 our-circle
的面积时,会根据此类所定义的方法来计算。我们使用 来读取一个属性,用 tell
来调用一个方法:
> (rget 'radius our-circle)
2
T
> (tell our-circle 'area)
的确有一个秘诀存在,但不是编程的奇技淫巧。这个秘诀是,Lisp 本来就是一个面向对象的语言了,甚至说,是种更通用的语言。我们需要做的事情,不过就是把本来就存在的抽象,再重新包装一下。