返回介绍

5.1 共享方法定义

发布于 2025-02-20 00:17:08 字数 2109 浏览 0 评论 0 收藏 0

为了支持不同的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文