Object Orientation
In most OOP systems, methods belong to classes. In Common Lisp, methods are instances of generic functions, which can dispatch on not just the first argument, but every argument. This makes functions, rather than classes, the prime mover.
Generic Functions and Methods
We define a generic function with defgeneric
:
(defgeneric description (object)
(:documentation "Return a description of an object."))
And we define methods of that function with defmethod
:
(defmethod description ((object integer))
(format nil "The integer ~D" object))
(defmethod description ((object float))
(format nil "The float ~3,3f" object))
We can try them in the REPL:
CL-USER> (description 10)
"The integer 10"
CL-USER> (description 3.14)
"The float 3.140"
Classes
(defclass vehicle ()
((speed :accessor vehicle-speed
:initarg :speed
:type real
:documentation "The vehicle's current speed."))
(:documentation "The base class of vehicles."))
When the superclass list is empty, the default base class, standard-class
, is
used. You can change this, but that’s an advanced topic.
(defclass bicycle (vehicle)
((mass :reader bicycle-mass
:initarg :mass
:type real
:documentation "The bike's mass."))
(:documentation "A bicycle."))
(defclass canoe (vehicle)
((rowers :reader canoe-rowers
:initarg :rowers
:initform 0
:type (integer 0)
:documentation "The number of rowers."))
(:documentation "A canoe."))
Instantiate:
CL-USER> (defparameter canoe (make-instance 'canoe
:speed 10
:rowers 6))
CANOE
CL-USER> (class-of canoe)
#<STANDARD-CLASS COMMON-LISP-USER::CANOE>
CL-USER> (canoe-rowers canoe)
6
CL-USER> (vehicle-speed canoe)
10
We can get information about a class using describe
:
CL-USER> (describe 'canoe)
COMMON-LISP-USER::CANOE
[symbol]
CANOE names the standard-class #<STANDARD-CLASS
COMMON-LISP-USER::CANOE>:
Documentation:
A canoe.
Direct superclasses: VEHICLE
No subclasses.
Not yet finalized.
Direct slots:
ROWERS
Type: (INTEGER 0)
Initargs: :ROWERS
Initform: 0
Readers: CANOE-ROWERS
Documentation:
The number of rowers.