Мультидиспетчеризация не по типам - Lisp

Узнай цену своей работы

Формулировка задачи:

что то я везде встречаю примеры мультидиспетчеризаци по типам. А как в лиспе диспетчеризовать не по типам, а по друзим вещам, по слотам, например? Как будет выглядеть на лисповских мультиметодах аналог вот такого вот кода?
A := Object clone do(
    a := 0
    accept := method(visitor, visitor doA(self))
)
B := Object clone do(
    b := 0
    accept := method(visitor, visitor doB(self))
)

Visitor := Object clone do(
   doA := method(acceptor, acceptor a = acceptor a + 1)
   doB := method(acceptor, acceptor b = acceptor b + 1)
)

a := A clone
b := B clone
visitor := Visitor clone

list(a, b) foreach(acceptor, acceptor accept(visitor)) 

writeln(a a, b b) #>>>>11

Решение задачи: «Мультидиспетчеризация не по типам»

textual
Листинг программы
(defclass a-class ()
  ((a :initform 0 :accessor a)))
 
(defclass b-class ()
  ((b :initform 0 :accessor b)))
 
(defun do-a (obj)
  (incf (a obj)))
 
(defun do-b (obj)
  (incf (slot-value obj 'b)))
 
(defclass visitor () ())
 
(defgeneric accept (who whom))
 
(defmethod accept ((who a-class) (whom visitor))
  (declare (ignore whom))
  (do-a who))
 
(defmethod accept ((who b-class) (whom visitor))
  (declare (ignore whom))
  (do-b who))
 
(let ((a-guy (make-instance 'a-class))
      (b-guy (make-instance 'b-class))
      (visitor (make-instance 'visitor)))
  (dolist (acceptor (list a-guy b-guy))
    (accept acceptor visitor))
  (format t "~^~S ~S~%" (a a-guy) (b b-guy)))
; 1 1

Объяснение кода листинга программы

В коде определены два класса: a-class и b-class. У каждого из них есть свой атрибут: a и b соответственно. Также определены два метода: do-a и do-b, которые увеличивают значение соответствующего атрибута на единицу. Следующий класс — visitor — представляет собой посетитель, который используется для навещания объектов и увеличения их атрибутов. Определённый затем метод accept является общим для двух классов и увеличивает значение атрибута a или b в зависимости от того, какой класс навещает посетитель. Далее создаются два объекта: a-guy и b-guy, которые представляют собой экземпляры классов a-class и b-class соответственно. Затем создаётся объект visitor, который является экземпляром класса visitor. В цикле dolist перебираются два элемента — a-guy и b-guy. Для каждого из них вызывается метод accept, который увеличивает значение соответствующего атрибута на единицу. В конце выводится сообщение с значениями атрибутов a и b созданных объектов.

Оцени полезность:

14   голосов , оценка 3.786 из 5
Похожие ответы