Lisp CLOS中如何让类的setter自动更新另一个槽位?
CLOS中更新尺寸自动同步体积的解决方案
方案一:动态计算体积(推荐)
不需要将volume作为存储槽,而是通过方法实时计算长宽高的乘积,确保每次访问都能得到最新值:
修改类定义(修正了原代码中breath的拼写错误为breadth):
(defclass box () ((length :accessor box-length :initform 0 :initarg :bxl) (breadth :accessor box-breadth :initform 0 :initarg :bxb) (height :accessor box-height :initform 0 :initarg :bxh)))
定义volume方法:
(defmethod volume ((b box)) (* (box-length b) (box-breadth b) (box-height b)))
简化构造函数,无需手动传入体积:
(defun make-box (l b h) (make-instance 'box :bxl l :bxb b :bxh h))
测试验证:
(defparameter my-box (make-box 4 3 2)) (volume my-box) ; 返回24 (setf (box-height my-box) 5) (volume my-box) ; 返回60
这种方式消除了冗余存储,从根本上避免数据不一致,更贴合CLOS的设计思路。
方案二:保留体积槽,重写setf方法
若必须存储volume值,可重写尺寸属性的setf方法,在更新尺寸后自动同步体积:
类定义(保留volume槽,移除手动传入的:initarg):
(defclass box () ((length :accessor box-length :initform 0 :initarg :bxl) (breadth :accessor box-breadth :initform 0 :initarg :bxb) (height :accessor box-height :initform 0 :initarg :bxh) (volume :reader volume :initform 0)))
定义体积更新的辅助方法:
(defmethod update-volume ((b box)) (setf (slot-value b 'volume) (* (box-length b) (box-breadth b) (box-height b))))
重写各尺寸的setf方法:
(defmethod (setf box-length) (new-val (b box)) (setf (slot-value b 'length) new-val) (update-volume b)) (defmethod (setf box-breadth) (new-val (b box)) (setf (slot-value b 'breadth) new-val) (update-volume b)) (defmethod (setf box-height) (new-val (b box)) (setf (slot-value b 'height) new-val) (update-volume b))
构造函数初始化时同步体积:
(defun make-box (l b h) (let ((box (make-instance 'box :bxl l :bxb b :bxh h))) (update-volume box) box))
测试验证:
(defparameter my-box (make-box 4 3 2)) (volume my-box) ; 返回24 (setf (box-height my-box) 5) (volume my-box) ; 返回60
这种方式需要维护多个setf方法,适合有特定存储需求的场景。
内容的提问来源于stack exchange,提问作者Todd
相关产品推荐
相关产品推荐

