Multimethods vs. Method Overloading

    Programmers used to statically typed message-passing languages such as Java and C++ may think multimethods sound similar to a feature of those languages called method overloading. However, these two language features are actually quite different since overloaded methods are chosen at compile time, based on the compile-time type of the arguments, not at runtime. To see how this works, consider the following two Java classes:

    1. public void foo(A a) { System.out.println("B/A"); }
    2. }

    When you tell to instantiate an A, it prints “A/A” as you’d probably expect.

    1. bash$ java com.gigamonkeys.Main A

    However, if you tell Main to instantiate a , then the true type of obj is taken into account for only half the dispatching.

    Multimethods are perfect for all those situations where, in a message-passing language, you struggle to decide to which class a certain behavior ought to belong. Is the sound a drum makes when it’s hit with a drumstick a function of what kind of drum it is or what kind of stick you use to hit it? Both, of course. To model this situation in Common Lisp, you simply define a generic function beat that takes two arguments.

    1. (defgeneric beat (drum stick)
    2. (:documentation

    Then you can define various multimethods to implement beat for the combinations you care about. For example:

    Multimethods also save you from having to tightly couple one set of classes with the other. In the drum/stick example, nothing requires the implementation of the drum classes to know about the various classes of drumstick, and nothing requires the drumstick classes to know anything about the various classes of drum. The multimethods connect the otherwise independent classes to describe their joint behavior without requiring any cooperation from the classes themselves.