Один из подходов к этому - использовать вторичный метод инициализации:
(defclass myclass ()
((s1 :initarg :s1 :accessor s1)))
(defgeneric initialize-myclass (dispatch class &key))
(defmethod initialize-instance :after ((c myclass) &rest args &key (dispatch 'normal)
&allow-other-keys)
(apply #'initialize-myclass dispatch c args))
(defmethod initialize-myclass ((dispatch (eql 'normal)) (class myclass) &key))
(defmethod initialize-myclass ((dispatch (eql 'special)) (class myclass)
&key x &allow-other-keys)
(print x))
Теперь вы можете сказать
(make-instance 'myclass :dispatch 'special ...)
Например. Обратите внимание, что это не обязательно хороший способ сделать это, но он работает, и я использовал это. Заметьте также, что у меня может быть неправильное значение по умолчанию для аргумента-ключевого слова: я никогда не помню, где вам нужно сказать &allow-other-keys
, а где нет, и где правильное место, чтобы сказать, что это.
Основная проблема здесь в том, что мы хотим, чтобы отправлялась дополнительная вещь: initialize-instance
может отправлять данные по классу определяемого объекта, но это all , по которому оно может отправляться. В частности, он не может отправить один из аргументов ключевого слова, потому что вы не можете сделать это в CLOS. Но мы можем взять один из его ключевых аргументов (dispatch
здесь) и «благословить» его в качестве позиционного аргумента для универсальной функции вторичной инициализации, которая затем может отправить этот аргумент.