Classes et instances

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))
  (setf (slot-value x 'bidule) val))

Irene DURAND
2011-10-14