Recherche…


Créer une classe CLOS de base sans parents

Une classe CLOS est décrite par:

  • un nom
  • une liste de superclasses
  • une liste de slots
  • autres options comme la documentation

Chaque slot a:

  • un nom
  • un formulaire d'initialisation (facultatif)
  • un argument d'initialisation (facultatif)
  • un type (facultatif)
  • une chaîne de documentation (facultatif)
  • fonctions d'accesseur, de lecteur et / ou de graveur (facultatif)
  • autres options comme l'allocation

Exemple:

(defclass person ()
  ((name
    :initform      "Erika Mustermann" 
    :initarg       :name 
    :type          string
    :documentation "the name of a person"
    :accessor      person-name)
   (age
    :initform      25
    :initarg       :age
    :type          number
    :documentation "the age of a person"
    :accessor      person-age))
  (:documentation "a CLOS class for persons with name and age"))

Une méthode d'impression par défaut:

(defmethod print-object ((p person) stream)
  "The default print-object method for a person"
  (print-unreadable-object (p stream :type t :identity t)
    (with-slots (name age) p
      (format stream "Name: ~a, age: ~a" name age))))

Création d'instances:

CL-USER > (make-instance 'person)
#<PERSON Name: Erika Mustermann, age: 25 4020169AB3>

CL-USER > (make-instance 'person :name "Max Mustermann" :age 24)
#<PERSON Name: Max Mustermann, age: 24 4020169FEB>

Mixins et interfaces

Common Lisp n'a pas d'interfaces dans le sens où certains langages (par exemple, Java), et il y a moins besoin de ce type d'interface étant donné que Common Lisp prend en charge plusieurs fonctions d'héritage et génériques. Cependant, le même type de modèle peut être facilement réalisé en utilisant des classes mixin. Cet exemple montre la spécification d'une interface de collection avec plusieurs fonctions génériques correspondantes.

;; Specification of the COLLECTION "interface"

(defclass collection () ()
  (:documentation "A collection mixin."))

(defgeneric collection-elements (collection)
  (:documentation "Returns a list of the elements in the collection."))

(defgeneric collection-add (collection element)
  (:documentation "Adds an element to the collection."))

(defgeneric collection-remove (collection element)
  (:documentation "Removes the element from the collection, if it is present."))

(defgeneric collection-empty-p (collection)
  (:documentation "Returns whether the collection is empty or not."))

(defmethod collection-empty-p ((c collection))
  "A 'default' implementation of COLLECTION-EMPTY-P that tests
whether the list returned by COLLECTION-ELEMENTS is the empty
list."
  (endp (collection-elements c)))

Une implémentation de l'interface est juste une classe qui a le mixin comme l'une de ses super-classes et des définitions des fonctions génériques appropriées. (À ce stade, notez que la classe mixin est uniquement destinée à signaler l'intention que la classe implémente "l'interface". Cet exemple fonctionnerait tout aussi bien avec quelques fonctions génériques et une documentation indiquant qu'il existe des méthodes sur la fonction pour la classe.)

;; Implementation of a sorted-set class

(defclass sorted-set (collection)
  ((predicate
    :initarg :predicate
    :reader sorted-set-predicate)
   (test
    :initarg :test
    :initform 'eql
    :reader sorted-set-test)
   (elements
    :initform '()
    :accessor sorted-set-elements
    ;; We can "implement" the COLLECTION-ELEMENTS function, that is,
    ;; define a method on COLLECTION-ELEMENTS, simply by making it
    ;; a reader (or accessor) for the slot.
    :reader collection-elements)))

(defmethod collection-add ((ss sorted-set) element)
  (unless (member element (sorted-set-elements ss)
                  :test (sorted-set-test ss))
    (setf (sorted-set-elements ss)
          (merge 'list
                 (list element)
                 (sorted-set-elements ss)
                 (sorted-set-predicate ss)))))

(defmethod collection-remove ((ss sorted-set) element)
  (setf (sorted-set-elements ss)
        (delete element (sorted-set-elements ss))))

Enfin, on peut voir à quoi ressemble une instance de la classe triée quand on utilise les fonctions "interface":

(let ((ss (make-instance 'sorted-set :predicate '<)))
  (collection-add ss 3)
  (collection-add ss 4)
  (collection-add ss 5)
  (collection-add ss 3)
  (collection-remove ss 5)
  (collection-elements ss))
;; => (3 4)


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow