Pour définir une classe en CLOS, on utilise la macro defclass dont voici la syntaxe :
(defclass nom (superclasse ...)
(créneau-1
créneau-2
...
créneau-n))
Les superclasses sont les classes dont celle-ci hérite. L'ordre entre les superclasses est important pour déterminer le comportement exact des instances de la classe; cependant, il est sans importance pour des applications simples.
Chaque créneau-i est une liste dont le premier élément est le nom du créneau (en Anglais : slot) et les autres éléments sont des options du créneau (en Anglais : slot options).
Les options du créneau sont des couples constitués d'un mot-clé et d'une valeur. Avec l'option :initform il est possible de donner une valeur initiale à une instance créée par make-instance. Exemple de McCLIM :
(defclass clx-port (port)
((display :initform nil)
(screen :initform nil)
(window :initform nil)
(color-table :initform (make-hash-table :test #'eq))
(font-table :initform (make-hash-table :test #'eq))))
L'expression qui suit le mot-clé :initform est évaluée à chaque fois qu'une instance de la classe est créée.
Avec l'option :initarg, on peut indiquer un argument mot-clé à utiliser avec make-instance pour donner une valeur initiale au créneau. Le mot-clé est souvent le même que le nom du créneau, mais pas toujours. Exemples de McCLIM :
(defclass standard-bounding-rectangle (bounding-rectangle)
((x-min :initarg :min-x)
(y-min :initarg :min-y)
(x-max :initarg :max-x)
(y-max :initarg :max-y)))
(defclass pane (standard-sheet-input-mixin
temporary-medium-sheet-output-mixin
sheet-transformation-mixin basic-sheet)
(...
(sr-width :initform nil :initarg :width)
(sr-height :initform nil :initarg :height)
(sr-max-width :initform nil :initarg :max-width)
(sr-max-height :initform nil :initarg :max-height)
(sr-min-width :initform nil :initarg :min-width)
(sr-min-height :initform nil :initarg :min-height)
...))
Le dernier exemple illustre l'utilisation simultanée de :initarg et :initform. Dans ce cas, si l'argument d'initialisation n'est pas fourni à make-instance, c'est la valeur de l'expression qui suit :initform qui est évaluée.
Voici quelques exemples d'utilisation de make-instance :
(make-instance 'standard-bounding-rectangle
:min-x (min x1 x2)
:min-y (min y1 y2)
:max-x (max x1 x2)
:max-y (max y1 y2))
(make-instance 'clx-graft
:port port :mirror (clx-port-window port)
:orientation orientation :units units)
Deux autres options de créneau sont souvent utiles : :reader et :accessor. Ce sont des abréviations pour la définition de méthodes dont le but est de accéder ou de modifier le créneau.
Une définition comme celle-ci :
(defclass machin ()
(truc :reader machin-truc)
(bidule :accessor machin-bidule))
est équivalente à
(defclass machin ()
(truc)
(bidule))
(defmethod machin-truc ((x machin))
(slot-value x 'truc))
(defmethod machin-bidule ((x machin))
(slot-value x 'bidule))
(defmethod (setf machin-bidule) (val (x machin))
(set (slot-value x 'bidule) val))