Common Lisp中的类的getter和setter

aud*_*row 2 lisp oop setter common-lisp clos

我经常有一个由另一个类列表组成的类.例如,我将有一个由向量​​组成的向量列表类.为了避免编写长语句,我编写了一个访问嵌入式类的方法.但是,这种方法只起吸气剂的作用; 我不能用它来设置插槽值.有没有办法使用方法来设置类槽值?

以下是一个最小的例子:

(defclass vector ()
  ((name :accessor vector-name
         :initarg :name)))

(defclass vector-list ()
  ((vectors :accessor vector-list-vectors
            :initarg :vectors)))

(defun make-vector-list ()
  (make-instance 'vector-list
    :vectors (list
               (make-instance 'vector :name 'v1)
               (make-instance 'vector :name 'v2))))

(defmethod access-vector-name ((vt vector-list) vector-idx)
  (vector-name (nth vector-idx (vector-list-vectors vt))))


;; returns V1
(print (access-vector-name (make-vector-list) 0))

;; Now, trying to set the same slot returns an error
;; How can I set the slot?
(setf (access-vector-name (make-vector-list) 0) 'new); --> error
Run Code Online (Sandbox Code Playgroud)

cor*_*ump 6

最简单的是写:

(setf (aref (access-vector-name ...) index) value)`
Run Code Online (Sandbox Code Playgroud)

但是如果你不想公开你有数组/向量的事实,你可以定义一个自定义setf扩展器.

首先,只在您的班级中定义access-vector-name为a :reader.然后:

(defun (setf access-vector-name) (newval obj index)
  (setf (aref (access-vector-name obj) index) newval))
Run Code Online (Sandbox Code Playgroud)

如果意图隐藏底层实现,可能access-vector-name是一个坏名字.