修改另一個插槽時更新插槽

CLOS MOP 提供了 hook slot-value-using-class,當訪問,讀取或修改插槽值時呼叫它。因為在這種情況下我們只關心修改,所以我們為 (setf slot-value-using-class) 定義了一個方法。

(defclass document ()
  ((id :reader id :documentation "A hash computed with the contents of every other slot")
   (title :initarg :title :accessor title)
   (body :initarg :body :accessor body)))

(defmethod (setf c2mop:slot-value-using-class) :after
    (new class (object document) (slot c2mop:standard-effective-slot-definition))
  ;; To avoid this method triggering a call to itself, we check that the slot
  ;; the modification occurred in is not the slot we are updating.
  (unless (eq (slot-definition-name slot) 'id)
    (setf (slot-value object 'id) (hash-slots object))))

請注意,因為在例項建立時沒有呼叫 slot-value,所以可能需要在 initialize-instance :after 方法中複製程式碼

(defmethod initialize-instance :after ((obj document) &key)
  (setf (slot-value obj 'id)
        (hash-slots obj)))