文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
5.1 共享方法定义
为了支持不同的 self
,就重复所有的方法定义并不合理。将共同部分(方法体)分解出来,将变量(绑定到 self
的对象)参数化更合理。
先试试不用宏来实现。回想一下,不使用宏的情况下,点对象的定义如下:
(define make-point
(λ (init-x)
(letrec ([self
(let ([x init-x])
(let ([methods (list (cons 'x? (λ () x))
(cons 'x! (λ (nx)
(set! x nx)
self)))])
(λ (msg . args)
(apply (cdr (assoc msg methods)) args))))])
self)))
如果将 (let ([methods...]))
从 (λ (init-x) ...)
中提取出来,我们就可以实现想要的方法定义的共享。但是这样的话,字段变量就不在方法体的作用域中了。具体地说,在这个例子中,这意味着 x
在两个方法中都没有绑定。这表明,除了 self
之外,方法还需要参数化于状态(字段值)之上。不过,好在 self
可以“持有”状态(它可以捕获其词法环境中的字段绑定)。只要找到通过 self
能够提取字段值(还有对其赋值)的方法就可以了。为此,我们的对象将支持两个特定的消息 -read
和 -write
:
(define make-point
(let ([methods (list (cons 'x? (λ (self)
(λ () (self '-read))))
(cons 'x! (λ (self)
(λ (nx)
(self '-write nx)
self))))])
(λ (init-x)
(letrec ([self
(let ([x init-x])
(λ (msg . args)
(case msg
[(-read) x]
[(-write) (set! x (first args))]
[else
(apply ((cdr (assoc msg methods)) self) args)])))])
self))))
请仔细研究这里的方法现在是如何参数化于 self
的,还有,要存取字段现在需要向 self
发送特殊消息。接下来再研究对象本身的定义:当收到消息时,它首先检查消息是否为 -read
或 -write
,如果是的话就进行存取操作。来试试这是否可行:
(define p1 (make-point 1))
(define p2 (make-point 2))
> ((p1 'x! 10) 'x?)
10
> (p2 'x?)
2
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论