LISP Tutorial on LISP CLOS

common lisp predated the advance of object-oriented programming by couple of decades. however, it object-orientation was incorporated into it at a later stage.

defining classes

the defclass macro allows creating user-defined classes. it establishes a class as a data type. it has the following syntax −

(defclass class-name (superclass-name*)
   (slot-description*)
   class-option*))

the slots are variables that store data, or fields.

a slot-description has the form (slot-name slot-option*), where each option is a keyword followed by a name, expression and other options. most commonly used slot options are −

  • :accessor function-name

  • :initform expression

  • :initarg symbol

for example, let us define a box class, with three slots length, breadth, and height.

(defclass box () 
   (length 
   breadth 
   height)
)

providing access and read/write control to a slot

unless the slots have values that can be accessed, read or written to, classes are pretty useless.

you can specify accessors for each slot when you define a class. for example, take our box class −

(defclass box ()
   ((length :accessor length)
      (breadth :accessor breadth)
      (height :accessor height)
   )
)

you can also specify separate accessor names for reading and writing a slot.

(defclass box ()
   ((length :reader get-length :writer set-length)
      (breadth :reader get-breadth :writer set-breadth)
      (height :reader get-height :writer set-height)
   )
)

creating instance of a class

the generic function make-instance creates and returns a new instance of a class.

it has the following syntax −

(make-instance class {initarg value}*)

example

let us create a box class, with three slots, length, breadth and height. we will use three slot accessors to set the values in these fields.

create a new source code file named main.lisp and type the following code in it.

(defclass box ()
   ((length :accessor box-length)
      (breadth :accessor box-breadth)
      (height :accessor box-height)
   )
)
(setf item (make-instance 'box))
(setf (box-length item) 10)
(setf (box-breadth item) 10)
(setf (box-height item) 5)
(format t "length of the box is ~d~%" (box-length item))
(format t "breadth of the box is ~d~%" (box-breadth item))
(format t "height of the box is ~d~%" (box-height item))

when you execute the code, it returns the following result −

length of the box is 10
breadth of the box is 10
height of the box is 5

defining a class method

the defmethod macro allows you to define a method inside the class. the following example extends our box class to include a method named volume.

create a new source code file named main.lisp and type the following code in it.

(defclass box ()
   ((length :accessor box-length)
      (breadth :accessor box-breadth)
      (height :accessor box-height)
      (volume :reader volume)
   )
)

; method calculating volume   

(defmethod volume ((object box))
   (* (box-length object) (box-breadth object)(box-height object))
)

 ;setting the values 

(setf item (make-instance 'box))
(setf (box-length item) 10)
(setf (box-breadth item) 10)
(setf (box-height item) 5)

; displaying values

(format t "length of the box is ~d~%" (box-length item))
(format t "breadth of the box is ~d~%" (box-breadth item))
(format t "height of the box is ~d~%" (box-height item))
(format t "volume of the box is ~d~%" (volume item))

when you execute the code, it returns the following result −

length of the box is 10
breadth of the box is 10
height of the box is 5
volume of the box is 500

inheritance

lisp allows you to define an object in terms of another object. this is called inheritance. you can create a derived class by adding features that are new or different. the derived class inherits the functionalities of the parent class.

the following example explains this −

example

create a new source code file named main.lisp and type the following code in it.

(defclass box ()
   ((length :accessor box-length)
      (breadth :accessor box-breadth)
      (height :accessor box-height)
      (volume :reader volume)
   )
)

; method calculating volume   
(defmethod volume ((object box))
   (* (box-length object) (box-breadth object)(box-height object))
)
  
;wooden-box class inherits the box class  
(defclass wooden-box (box)
((price :accessor box-price)))

;setting the values 
(setf item (make-instance 'wooden-box))
(setf (box-length item) 10)
(setf (box-breadth item) 10)
(setf (box-height item) 5)
(setf (box-price item) 1000)

; displaying values
(format t "length of the wooden box is ~d~%" (box-length item))
(format t "breadth of the wooden box is ~d~%" (box-breadth item))
(format t "height of the wooden box is ~d~%" (box-height item))
(format t "volume of the wooden box is ~d~%" (volume item))
(format t "price of the wooden box is ~d~%" (box-price item))

when you execute the code, it returns the following result −

length of the wooden box is 10
breadth of the wooden box is 10
height of the wooden box is 5
volume of the wooden box is 500
price of the wooden box is 1000