| Liste Articles: [0-A] [A-C] [C-F] [F-J] [J-M] [M-P] [P-S] [S-Z] | Liste Catégories | Une page au hasard | Pages liées | ||||||
Cette page est
considérée comme un article à
approfondir.![]() |
| Cet article fait partie de la série Langages de programmation |
| Langages orientés objet |
| Ada 95 - C++ - C# Common lisp object system Delphi - Eiffel - Java - Nice |
| Langages impératifs |
| APL - ASP Assembleur BASIC - C - Pascal Perl - PHP - Python |
| Langages fonctionnels |
| ML/OCaml
- Lisp/Common Lisp Forth - Logo - Scheme |
| Langages déclaratifs |
| Clips - Prolog |
| Voir aussi |
| Conception - Codage Tests - Optimisations |
Le Common Lisp Object System, souvent abrégé en CLOS (prononcé 'si-lauss'), est l'ensemble des
primitives présentes dans le langage de
programmation Common Lisp pour construire un programme orienté objet. Il existe également une version de CLOS pour le langage
Scheme, nommée TinyClos.
| Sommaire |
CLOS est un système objet à classes (il existe des systèmes à prototypes). Il descend de flavors et common loops, développés dans les années 1980. Common Lisp a été le premier langage à objet standardisé par l'ANSI, en 1995, précédant de peu SmallTalk.
D'un certain point de vue, Lisp est un langage orienté objet depuis le début : les structures de données manipulées ont une identité et sont réflexives. La seule chose qui lui manquait pour recevoir l'estampille orienté objet, c'est la capacité d'étendre le système de types de Lisp.
(defclass foo () ()) ;; équivalent de (defclass foo (Object) ())
Par défaut, une classe est un sous-type de Object. Les types par défaut de Common Lisp (nombres, chaînes, hashages, vecteurs, etc.) ne sont pas dérivables.
(make-instance 'foo)
À partir d'un exemple plus intéressant, on montre les principales caractéristiques :
(defclass graphe () ((noeuds :accessor noeuds :initform (make-hash-table)) (arcs :accessor arcs :initform (make-hash-table)))
(defclass noeud () ((data :accessor data :initarg :data) (in-arcs :accessor in-arcs :initform (make-hash-table)) (out-arcs :accessor out-arcs :initform (make-hash-table)))
(defclass arc () ((in-noeud :accessor in-noeud :initarg :in-noeud) (out-noeud :accessor out-noeud :initarg :out-noeud)))
Les attributs d'une classe sont nommés slots dans la terminologie de CLOS. Chaque slot est défini par une liste contenant au minimum son nom, en première position. Des accesseurs en lecture seule (:reader) ou lecture-écriture (:accessor ou la combinaison de :reader et :writer) peuvent être spécifiés, ainsi que la valeur initiale (:initform) et un nom pour donner une valeur au moment de l'instanciation. Ainsi, pour construire un nœud doté d'une boucle, on peut écrire :
(defparameter *un-noeud* (make-instance 'noeud)) (defparameter *un-arc* (make-instance 'arc :in-noeud *un-noeud* :out-noeud *un-noeud*))
(setf (gethash (in-arcs *un-noeud*) *un-arc*) *un-arc*) (setf (gethash (out-arcs *un-noeud*) *un-arc*) *un-arc*)
Ces manipulations de tables de hashage étant lourdes, on se construit un opérateur sethash pour en racourcir l'expression :
(defmacro sethash (key value hash) `(setf (gethash ,key ,hash) ,value))
Ainsi armé, on peut réécrire les deux lignes précédents :
(sethash (in-arcs *un-noeud*) *un-arc*) (sethash (out-arcs *un-noeud*) *un-arc*)
Voici la plus grande originalité de CLOS : les méthodes n'y sont pas définies sur une classe. Au lieu de cela, elles sont définies un tuple de classes. Par exemple, on veut simplifier la connexion des nœuds et des arcs.
Dans un langage à sélection simple, il faudrait attacher la méthode connecter à la classe nœud OU à la classe arrête, pour pouvoir écrire :
un_arc.connecter (un_noeud, un_autre_noeud)
Ou encore :
un_noeud.connecter (un_arc, un_autre_noeud)
Une méthode a un paramètre privilégié, son receveur (au sens de la réception d'un message). La notation pointée souligne ce privilège.
Avec la sélection multiple de la méthode sur le tuple des arguments obligatoires, on n'a plus besoin de choisir :
(defgeneric connecter ((noeud noeud arc))
Une fonction générique est un sac de méthodes. On y place la première :
(defmethod connecter ((noeud-1 noeud) (noeud-2 noeud) (un-arc arc)) (setf (in-noeud un-arc) noeud-1) (setf (out-noeud un-arc) noeud-2) (sethash out-arcs noeud-1 un-arc) (sethash in-arcs noeud-2 un-arc))
On peut maintenant écrire, pour construire la boucle :
(connecter *un-noeud* *un-noeud* *un-arc*)
(... à continuer ...)


