Search code examples
overridingcommon-lispaccessorclos

Common Lisp: how to override slot accessors?


I'd like to control the way the values are saved in slots and what is returned when I read a slot. Here is my class definition:

(defclass object ()
  ((name :accessor name-access
         :initform 'noname
         :initarg :name)
   (value :accessor value-access
      :initform 10
      :initarg :value)))

I create the object this way:

(setf obj1 (make-instance 'object))

This is the way how I get the value of the slot name:

(name-access obj1)

And how I set a new value:

(setf (name-access obj1) 'realname)

What is the right way to override this accessor function (or method) in order to be able to make some changes to the object (on write) and to control the returned value?

Thank you.


Solution

  • You can just manually define the methods for getting and setting the slots:

    (defclass foo ()
      ((name :initform 'noname
             :initarg :name)))
    
    (defgeneric name-access (foo)
      (:method ((foo foo))
        (format t "~&Getting name.~%")
        (slot-value foo 'name)))
    
    (defgeneric (setf name-access) (name foo)
      (:method (name (foo foo))
        (format t "~&Setting a new name.~%")
        (setf (slot-value foo 'name) name)))
    
    (defparameter *foo* (make-instance 'foo))
    (name-access *foo*)
    ; Getting name.
    ;=> NONAME
    
    (setf (name-access *foo*) 'some-name)
    ; Setting a new name.
    ;=> SOME-NAME
    
    (name-access *foo*)
    ; Getting name.
    ;=> SOME-NAME
    

    The book Practical Common Lisp goes through these in chapter 17. You should read that.