Multiple Dispatch¶
“Multiple dispatch” is one of the most powerful and elegant features of Dylan. As explained in the section on generic functions and objects, Dylan methods are declared separately from the classes upon which they act. Polymorphism, the specialization of methods for use with particular classes, can be implemented by declaring several methods with different parameters and attaching them to one generic function:
define generic inspect-vehicle (v :: <vehicle>, i :: <inspector>) => ();
define method inspect-vehicle (v :: <vehicle>, i :: <inspector>) => ()
look-for-rust(v);
end;
define method inspect-vehicle (car :: <car>, i :: <inspector>) => ()
next-method(); // perform vehicle inspection
check-seat-belts(car);
end;
define method inspect-vehicle (truck :: <truck>, i :: <inspector>) => ()
next-method(); // perform vehicle inspection
check-cargo-attachments(truck);
end;
However, different types of vehicle inspectors may have different
policies. A state inspector, in addition to the usual procedures, will
also typically check a car’s insurance policy. To implement this, add
another method to the generic function inspect-vehicle
:
define method inspect-vehicle (car :: <car>, i :: <state-inspector>) => ()
next-method(); // perform car inspection
check-insurance(car);
end;
let inspector = make(<state-inspector>);
let car = make(<car>);
inspect-vehicle(car, inspector);
Calling the generic function inspect-vehicle
with these arguments performs three separate tasks:
look-for-rust
, check-seat-belts
and
check-insurance
. The most specific method on
inspect-vehicle
– the one for the classes
<car>
and <state-inspector>
– is invoked first
and calls next-method
to invoke the less-specific methods in turn.
For an exact definition of “specific”, see method dispatch
in the DRM.
Dispatching on Specific Objects¶
Dylan also allows functions to dispatch on specific objects. For
example, state inspectors might pass the governor’s car without
actually looking at it. Dylan expresses this situation using
singletons
, objects which are treated as
though they were in a class of their own. For example:
define constant $governors-car = make(<car>);
define method inspect-vehicle
(car == $governors-car, i :: <state-inspector>) => ()
wave-through(car);
end;
The car
parameter is specialized via == $governors-car
, meaning “the
object identical to $governors-car”. (In this example, none of the usual
inspection methods are invoked since the above code doesn’t call
next-method
.)