Neither STKLOS nor CLOS use the message mechanism for methods as most Object Oriented language do. Instead, they use the notion of generic function. A generic function can be seen as a methods ``tanker''. When the evaluator requestd the application of a generic function, all the methods of this generic function will be grabbed and the most specific among them will be applied. We say that a method M is more specific than a method M' if the class of its parameters are more specific than the M' ones. To be more precise, when a generic funtion must be ``called'' the system will
The definition of a generic function is done with the ndexfile(index-entry "define-generic" "tt" aux )define-generic macro. Definition of a new method is done with the ndexfile(index-entry "define-method" "tt" aux )define-method macro. Note that ndexfile(index-entry "define-method" "tt" aux )define-method automatically defines the generic function if it has not been defined before. Consequently, most of the time, the ndexfile(index-entry "define-generic" "tt" aux )define-generic needs not be used.
Consider the following definitions:
unspecified
error
makeotherˆ`=̀13`
gobblecr(define-generic M)(define-method M((a <integer>) b) 'integer)(define-method M((a <real>) b) 'real)(define-method M(a b) 'top)
The ndexfile(index-entry "define-generic" "tt" aux )define-generic call defines M as a generic function. Note that the signature of the generic function is not given upon definition, contrarily to CLOS. This will permit methods with different signatures for a given generic function, as we shall see later. The three next lines define methods for the M generic function. Each method uses a sequence of parameter specializers that specify when the given method is applicable. A specializer permits to indicate the class a parameter must belong to (directly or indirectly) to be applicable. If no speciliazer is given, the system defaults it to ndexfile(index-entry "<top>" "tt" aux )<top>. Thus, the first method definition is equivalent to
unspecified
error
makeotherˆ`=̀13`
gobblecr(define-method M((a <integer>) (b <top>)) 'integer)
Now, let us look at some possible calls to generic function M:
unspecified
error
makeotherˆ`=̀13`
gobblecr(M 2 3) integer(M 2 #t) integer(M 1.2 'a) real(M #3 'a) real(M #t #f) top(M 1 2 3) error (since no method exists for 3 parameters)
The preceding methods use only one specializer per parameter list. Of course,
each parameter can use a specializer. In this case, the parameter list is scanned
from left to right to determine the applicability of a method. Suppose we declare
now
unspecified
error
makeotherˆ`=̀13`
gobblecr(define-method M ((a <integer>) (b <number>)) 'integer-number)(define-method M ((a <integer>) (b <real>)) 'integer-real)(define-method M (a (b <number>)) 'top-number)
In this case,
unspecified
error
makeotherˆ`=̀13`
gobblecr(M 1 2) integer-integer(M 1 1.0) integer-real(M 1 #t) integer(M 'a 1) 'top-number