common-lisp
CLOS - Common Lisp Object System
Sök…
Skapa en grundläggande CLOS-klass utan föräldrar
En CLOS-klass beskrivs av:
- ett namn
- en lista med superklass
- en lista med slots
- ytterligare alternativ som dokumentation
Varje kortplats har:
- ett namn
- ett initialiseringsformulär (valfritt)
- ett initialiseringsargument (valfritt)
- en typ (valfritt)
- en dokumentationssträng (valfritt)
- accessor, läsare och / eller författarfunktioner (valfritt)
- ytterligare alternativ som tilldelning
Exempel:
(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"))
En standardutskriftsmetod:
(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))))
Skapa instanser:
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 och gränssnitt
Common Lisp har inte gränssnitt i den meningen att vissa språk (t.ex. Java) gör det, och det finns mindre behov av den typen av gränssnitt eftersom Common Lisp stöder flera arv och generiska funktioner. Dock kan samma typ av mönster realiseras enkelt med mixinklasser. Detta exempel visar specifikationen för ett samlingsgränssnitt med flera motsvarande generiska funktioner.
;; 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)))
En implementering av gränssnittet är bara en klass som har mixin som en av dess superklasser och definitioner av lämpliga generiska funktioner. (Vid denna punkt, lägg märke till att mixin-klassen egentligen bara är för att signalera avsikten att klassen implementerar "gränssnittet". Detta exempel skulle fungera lika bra med några generiska funktioner och dokumentation som säger att det finns metoder på funktionen för klassen.)
;; 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))))
Slutligen kan vi se hur en instans av den sorterade klassen ser ut när man använder "gränssnitt" -funktionerna:
(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)