(Also Gates.lisp handout):initform
(defclass Foo ()
((Slot-1 :initform 3)
(Slot-2 :initform '(A B)))
C. slot-value, (setf slot-value), :initarg
D. :reader, :writer, :accessor
(defmethod Square ((X number)) (* X X))
(defmethod Square ((S string)) (format nil "~A~A" S S))
Note common error of omitting () above.
(defmethod Area ((C Circle)) (* pi (Square (Radius C)))
(defmethod Area ((R Rectangle)) (* (Width R) (Height R)))
(defmethod Area ((Sq Square)) (Square (Width Sq)))
OR (defmethod Height ((Sq Square)) (Width Sq))
Point: several can apply, but only most specific wins. Which one gets invoked ("dispatch") is decided at run-time, in contrast to many other languages with "overloading".
Idea of error-catching method: Arg = (Arg t)
(defmethod Area (Arg)
(error "Area only defined for Circles, Rectangles, and Squares"))
(defmacro Define-Class (Class-Name Superclass-List &rest Slot-Descriptions)
'(defclass ,Class-Name ,Superclass-List
,(mapcar #'Expand-Slot-Entry Slot-Descriptions)))
(defun Expand-Slot-Description (Slot-Description)
(let ((Name (first Slot-Description))
(Value (second Slot-Description)) )
(list
Name
:accessor Name
:initarg (Add-Colon Name)
:initform value)))
;;; Like (read-from-string (format nil ":~A" Symbol))
(defun Add-Colon (Symbol) (intern (symbol-name Symbol) :keyword))

(Area Object-1) = (funcall (method-for 'Area Object-1) Object-1)
= (send Object-1 :Area) ; MRH -Flavors
C. Example (from Norvig) [assume no built-in "append"]
;;; Two strings: just call CONCATENATE
(defmethod Concat ((S1 string) (S2 string))(concatenate 'string S1 S2))
;;; Two lists: just call APPEND
(defmethod Concat ((L1 list) (L2 list))(append L1 L2))
;;; A list and a string: convert the list into one big string, then call Concat,
;;; to let the string/string version handle it. Note that we use PRINC-TO-STRING
;;; instead of just STRING, since STRING fails on numbers.
(defmethod Concat ((L1 list) (S1 string))
(Concat (apply #'concatenate 'string (mapcar #'princ-to-string L1))
S1))
;;; A string and a list: just call Concat with the args in the opposite order, to
;;; let the above version handle it.
(defmethod Concat ((S1 string) (L1 list))
(Concat L1 S1))
;;;Error-catching method
(defmethod Concat (X Y) (error "..."))
You cannot specialize on &optional , &rest or &key variables. I.e. same number of required args. Steele calls this "lambda list congruence".
(defmethod Color ((Obj Graphical-Object)) (slot-value Obj 'Color))
but :accessor Color also lets us do (setf (Color Obj) 'Red)
(defmethod (setf Color) (New-Color (Obj Graphical-Object))
(setf (slot-value Obj 'Color) New-Color))
D. Example: non-CLOS
(defun Add-SOme (X) (+ X *Global-Var*))
(defmethod (setf Add-Some) ((Result number) (X number))
(setq *Global-Var* (- Result X)))
(defmethod (setf Area) ((New-Area number) (C Circle))
(setf (Radius C) (sqrt (/ New-Area pi))))
B. Examples:
(defmethod Attach :before ((G1 Gate) (G2 Gate)) (Draw-New-Picture G1 G2))
(defmethod initialize-instance :after ((Obj Gate) &rest Extra-Args)
(declare (ignore Extra-Args))
(push Obj *Active-Gates*))
;;; Updating area each time instead of calculating it as before
(defmethod (setf Radius) :after ((New-Radius number) (C Circle))
(setf (Area C) (* pi (Square New-Radius))))
(defmethod Area :before ((R Rectangle))
(unless
(slot-boundp R 'Height)
(setf (Height R) (Width R))))
B. eql specializers
(defmethod Fact ((N (eql 0))) 1)
(defmethod Fact ((N integer)) (* N (Fact (- N 1))))
Methods are slower, but perhaps it is doing the same tests you are anyhow.
Around methods, user-definable method combination, slot-names, :allocation :class, etc.