Поиск…


Создание базового класса CLOS без родителей

Класс CLOS описывается:

  • имя
  • список суперклассов
  • список слотов
  • дополнительные параметры, такие как документация

Каждый слот имеет:

  • имя
  • форма инициализации (необязательно)
  • аргумент инициализации (необязательно)
  • тип (необязательно)
  • строка документации (необязательно)
  • функции доступа, чтения и / или записи (необязательно)
  • дополнительные варианты, такие как распределение

Пример:

(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"))

Метод печати по умолчанию:

(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))))

Создание экземпляров:

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>

Миксины и интерфейсы

Common Lisp не имеет интерфейсов в том смысле, что некоторые языки (например, Java) работают, и меньше необходимости в этом типе интерфейса, учитывая, что Common Lisp поддерживает множественные наследования и общие функции. Тем не менее, тот же тип шаблонов может быть легко реализован с использованием классов mixin. В этом примере показана спецификация интерфейса коллекции с несколькими соответствующими универсальными функциями.

;; 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)))

Реализация интерфейса - это просто класс, который имеет mixin как один из его суперклассов и определения соответствующих общих функций. (На этом этапе обратите внимание, что класс mixin действительно предназначен только для сигнализации о том, что класс реализует «интерфейс». Этот пример будет работать также с несколькими универсальными функциями и документацией, в которых говорится, что существуют методы для функции класс.)

;; 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))))

Наконец, мы видим, что использование экземпляра класса отсортированного набора выглядит при использовании «интерфейсных» функций:

(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
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow