当前位置:  开发笔记 > 编程语言 > 正文

Common Lisp类槽的访问器函数

如何解决《CommonLisp类槽的访问器函数》经验,为你挑选了1个好方法。

我正在阅读Peter Seibel的Practical Common Lisp中有关类的章节,我对使用访问器函数感到困惑.

SETF

我不理解setf下面给出的涉及银行账户和客户名称的功能的新定义:

(defun (setf customer-name) (name account)
  (setf (slot-value account 'customer-name) name))

它使用如下:

(setf (customer-name my-account) "Sally Sue")

为什么定义setf采用两个参数(name account),但那不是我们提供的?customer-name上面的函数是否与customer-name稍后定义的读者函数有关(见下文)?

(defgeneric (setf customer-name) (value account))

(defmethod (setf customer-name) (value (account bank-account))
  (setf (slot-value account 'customer-name) value))

直接插槽访问

访问器功能的动机是避免直接访问插槽; 接口实现和所有这些.但Common Lisp提供了:reader,:writer:accessor插槽选项来做到这一点.例如

(customer-name
 :initarg :customer-name
 :initform (error "Must supply a customer name.")
 :accessor customer-name)

我是否正确理解这应该只用于直接访问绝对正常的插槽?因为如果我们稍后决定应该直接访问插槽,我们就会破坏它们.



1> malisper..:

setf有点神奇.关键setf是要设置一个类似于访问该值的语法的语法.对于setf使用defun(或defmethod)定义函数的情况,(setf (f ...) val)变为等效(funcall #'(setf f) val ...).这就是为什么setf在你的例子中只需要一个参数; 传递给的第二个参数(setf customer-name)my-account.如果你想了解更多关于内部的内容setf,我写了一篇关于它的博客文章,你可以在这里找到.

因为它是如此普遍写读者和作家的插槽,defclass提供了:reader,:writer:accessor选项.当您传入其中一个选项时,defclass将自动编写相应的读者和作者.例如,插槽定义:

(customer-name
  :accessor customer-name
  ...)

会自动编写代码:

(defgeneric customer-name (account))

(defmethod customer-name ((account bank-account))
  (slot-value account 'customer-name))

(defgeneric (setf customer-name) (value account))

(defmethod (setf customer-name) (value (account bank-account))
  (setf (slot-value account 'customer-name) value))

为了你!

至于你直接访问插槽的问题,我看到的最常见的模式是为所有插槽创建访问器,然后只导出应该可以直接访问的插槽的访问器.这样,您可以直接从定义类的同一个包中访问所有插槽,但是从另一个包中,您只能访问"导出"插槽.

推荐阅读
雨天是最美
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有