CLOS не имеет понятия "это" или "я", потому что с помощью универсальных функций любой экземпляр, с которым выполняется действие, передается в качестве аргумента.
Итак, учитывая ваш пример сметод доступа mn-pai
:
(setf instance (make-instance 'mn))
(mn-pai instance 1)
Здесь instance
передается в качестве аргумента метода доступа.
Если вы создали метод:
(defmethod inc-pai (an-mn amount)
(incf (mn-pai an-mn) amount))
Опять же, вы видите, что экземпляр передается в качестве первого аргумента.Итак, всегда есть явный аргумент, который вы используете.
Теперь рассмотрим:
(defmethod inc-both (an-mn another-mn amount)
(incf (mn-pai an-mn) amount)
(incf (mn-pai another-mn) amount))
Итак, в обычной системе, основанной на классах, куда бы вы поместили этот метод?В служебном классе?Это метод класса "MN"?Это как бы не поддается готовой категоризации.
Теперь рассмотрим:
(defclass mn2 ()
((pai :accessor mn2-pai)))
, если бы мы сделали это:
(setf an-mn (make-instance 'mn))
(setf an-mn2 (make-instance 'mn2))
(inc-both an-mn an-mn2)
Вторая строка потерпит неудачу, как это делает mn2не имеет mn-pai
аксессора.
Однако это будет работать:
(defmethod inc-both2 (an-mn another-mn amount)
(incf (slot-value 'pai an-mn) amount)
(incf (slot-value 'pai another-mn) amount))
Поскольку slot-value
является примитивным аксессором для CLOS, и оба класса имеют слот с именем pai
.Но тогда вы не можете вызвать функцию доступа.Скорее вы устанавливаете слот напрямую.Наверное, не то, что вы хотите.И, конечно же, имена являются совпадением.Нет никакой связи между классами, сохраняющими их похожие имена и имя общего слота.
Но затем вы можете сделать это:
(defmethod inc-both ((mn an-mn) (mn2 another-mn) amount)
(incf (mn-pai an-mn) amount)
(incf (mn-pai2 another-mn) amount))
Это работает, потому что среда выполнения будет диспетчеризоваться на основе типовпараметры.Мы «знаем», что another-mn
является экземпляром mn2
, потому что мы сказали системе, что это должно быть, когда мы уточнили аргумент.
Но, опять же, вы можете видеть, как в системе на основе классов естьнет «места» для такого метода.Обычно мы просто создаем некоторый класс Utility и добавляем его туда, или обычную функцию в глобальном пространстве имен.
Хотя в CLOS есть классы, на самом деле это не система, основанная на классах.
Это также встречается в сценариях с множественным наследованием (которые поддерживает CLOS).Кто тогда "я"?