I am new to CLOS. Here is my example:
(defclass box ()
((length :accessor box-length :initform 0 :initarg :bxl)
(breath :accessor box-breadth :initform 0 :initarg :bxb)
(height :accessor box-height :initform 0 :initarg :bxh)
(volume :reader volume :initform 0 :initarg :v)))
And the constructor is:
(defun make-box (l b h)
(make-instance 'box :bxl l :bxb b :bxh h :v (* l b h)))
So when I make an instance of the 'box' like this:
; make a box, 4 x 3 x 2
(defparameter my-box (make-box 4 3 2))`
It works as I expected. I can 'describe' my-box and get:
(describe my-box)
#<BOX {100363F493}>
[standard-object]
Slots with :INSTANCE allocation:
LENGTH = 4
BREATH = 3
HEIGHT = 2
VOLUME = 24
Now, the question. If I update the 'height' like this:
(setf (box-height my-box) 5)
How can I make this 'setf' automatically update the 'volume' slot?
So that VOLUME would change to (* 4 3 5) = 60?
One way to do this is an after method on the
setfmethod of the various accessors. So:This could be done by a before method as well, but if you use a general 'update-the-volume' function you want to use an after method to avoid storing the slots twice, or define the
setfside of the accessor completely yourself.Another approach which is certainly simpler is to not have a volume slot at all but compute it:
Obviously other classes can still have a volume slot and methods on the
volumegeneric function can access that slot: the protocol is the same.You can even make
describereport the volume, either by defining a method ondescribe-objectforboxes, or just defining an after method. In the latter case in particular you probably have to fiddle to get the formatting to agree with whatever your implementation'sdescribedoes. Here is a method which coincidentally is OK for my usual implementation (LispWorks):Now