Re: [CLOS] Ensuring a method exists



On Wed, 27 Sep 2006 09:40:18 +0200, Didier Verna wrote:


Hi !

Suppose I have:

(defgeneric foo (a b) ...)

(defclass base () ...)
(defmethod foo ((a base) (b base)) ...)



I'd like to ensure that if somebody writes a derived class:

(defclass derived (base) ...)

she also provides a method for this class:

(defmethod foo ((a derived) (b derived)) ...)



I'd be happy with a dynamic solution. Perhaps, the method combination
would check that the first applicable method matches exactly the class of
the arguments. But I know nothing about the MOP yet ...

This seems to work:

(defclass SomeBase ()
())


(defmethod initialize-instance :before ((some-base SomeBase) &key)
(format t "Checking for `foo': ~A~%"
(find-method #'foo '() (mapcar #'find-class
(list (type-of some-base)
(type-of some-base))))))


(defmethod foo ((a SomeBase) (b SomeBase))
(write-line "(foo SomeBase SomeBase)"))


(defclass SomeDerived (SomeBase)
())

cl-user> (make-instance 'SomeBase)
Checking for `foo': #<standard-method foo (SomeBase SomeBase) {AB54379}>
#<SomeBase {ACEAF41}>
cl-user> (make-instance 'SomeDerived) ;; *bang!*
cl-user> (defmethod foo ((a SomeDerived) (b SomeDerived))
(write-line "(foo SomeDerived SomeDerived)"))
#<standard-method foo (SomeDerived SomeDerived) {AE59049}>
cl-user> (make-instance 'SomeDerived)
Checking for `foo': #<standard-method foo (SomeDerived
SomeDerived) {AE59049}>
#<SomeDerived {AE68A91}>
cl-user> (fmakunbound 'foo)
foo
cl-user> (make-instance 'SomeBase) ;; *bang!*
; Evaluation aborted
cl-user> (make-instance 'SomeDerived) ;; *bang!*
; Evaluation aborted

(I feel like Steve Jobs and his booooms! :))

You could add a handler in `initialize-instance' that would show a more
helpful message or whatever.

--
Lars Rune Nøstdal
http://lars.nostdal.org/

.



Relevant Pages