返回介绍

6.4 清理类协议

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

我们引入 类 之后,又对它的协议(protocol)做了不少改变:

  • 通过引入 lookupinvoke 协议分成两部分, lookup 专门用于在类的层次结构中查找方法定义。
  • 为了能够检索类的字段,添加了 all-fields 。构建类的时候通过它获取超类的字段列表,追加到当前定义的类的字段列表。
  • 去除了字段访问的 read / write 协议,以便正确地确定方法中的字段名称的作用域。

现在是时候反思一下类协议,看看这里的协议是不是最小化的,还是可以去掉一些部分。判断的标准是什么?既然我们正在讨论类的协议,它最好确实是依赖于类来处理消息。例如,之前介绍的 read / write 协议就可以删除。回忆一下:

....
[(read)  (dict-ref (obj-values (first vals)) (second vals))]
[(write) (dict-set! (obj-values (first vals)) (second vals)
                    (third vals))]
....

这里有任何东西依赖于类函数中的自由变量(或者说,依赖于类对象的状态)吗?没有,唯一需要的输入是当前对象、要访问的字段的名称,以及可能写入的值。因此,我们可以直接把这些代码放在 ?! 的展开中,从而有效地“编译掉”一层不必要的解释。

那么 invoke 呢? 来看看,它唯一做的是给自己发送一条消息,这个可以直接在扩展 -> 时做,这样调用本质上就独立于类了:

(defmac (-> o m arg ...)
  (let ([obj o])
    ((((obj-class obj) 'lookup 'm) obj) arg ...)))

类协议的其他部分呢? all-fieldscreatelookup 都访问了类的内部状态: all-fields 访问了 fieldscreate 访问了 fieldsclass 本身; lookup 访问了 methodssuperclass 。所以,我们的类只需要了解这三种信息。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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