common-lisp
CLOS: il Common Lisp Object System
Ricerca…
Creazione di una classe CLOS di base senza genitori
Una classe CLOS è descritta da:
- un nome
- una lista di superclassi
- una lista di slot
- ulteriori opzioni come documentazione
Ogni slot ha:
- un nome
- un modulo di inizializzazione (facoltativo)
- un argomento di inizializzazione (facoltativo)
- un tipo (facoltativo)
- una stringa di documentazione (opzionale)
- funzioni accessorie, lettore e / o scrittore (opzionale)
- ulteriori opzioni come l'assegnazione
Esempio:
(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"))
Un metodo di stampa predefinito:
(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))))
Creare istanze:
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>
Mixin e interfacce
Common Lisp non ha interfacce nel senso che alcuni linguaggi (ad esempio, Java) fanno, e c'è meno bisogno di quel tipo di interfaccia dato che Common Lisp supporta l'ereditarietà multipla e funzioni generiche. Tuttavia, lo stesso tipo di pattern può essere realizzato facilmente utilizzando le classi di mixin. Questo esempio mostra le specifiche di un'interfaccia di raccolta con diverse funzioni generiche corrispondenti.
;; 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)))
Un'implementazione dell'interfaccia è solo una classe che ha il mixin come una delle sue super classi e le definizioni delle funzioni generiche appropriate. (A questo punto, si noti che la classe di mixin è in realtà solo per segnalare l'intento che la classe implementa la "interfaccia" .Questo esempio funzionerebbe altrettanto bene con alcune funzioni e documentazione generiche che affermano che ci sono metodi sulla funzione per 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))))
Infine, possiamo vedere che cosa sta usando un'istanza della classe set ordinati quando si utilizzano le funzioni "interfaccia":
(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)