Мультидиспетчеризация не по типам - 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Решение задачи: «Мультидиспетчеризация не по типам»
(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 созданных объектов.