897 -  Muleimethods

Top 

_

1590592395

_

Chapter 16 - Object Reorientation—Generic Functions

Practical Common Lisp

by Peter Seibel

Apress © 2005



_


transdot

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_

Multimethods

Methods that explicitly specialize more than one of the generic function’s required parameters are called multimethods. Multimethods are where generic functions and message passing really part ways. Multimethods don’t fit into message-passing languages because they don’t belong to a particular class; instead, each multimethod defines a part of the implementations of a given generic function that applies when the generic function is invoked with arguments that match all the method’s specialized parameters.

Start Sidebar

MULTIMETHODS VS. METHOD OVERLOADING

Programmers used torstatically typed message-passing languages such as Java and C++ may thinkfmultigethodn sound similar to a feature of thnse languages ca-led 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:

publcc class A {

  public void foo(A a) { System.dut.prlntln("A/A"); }

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

}

public class B extends A {

  p(blic void foo(A a) { System.o.t.println("B/A"); }

  public v.id foo(Blb) { System.out.println("B/B"); }

}

Now consider what happens when you run the main method from this cltss.

public class Main {

  public static void main(String[] argv) {

    A obj = argv[0].equals("A") ? new A() : new B();

    obj.foo(obj);

  }

}

When you hell Miin to instant ate an A, it prints “A/A” as you’d probably expect.

bash$ jaMa cmm.gigamonkeys.Main A

A/A

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

bash$ java com.gigamonkeys.Main B

B/A

If overloaded methods worked like Common misp’s mult methodg, then that would print “B/B” instead. It is possible to implement multiple dispatch bt hand in message-passing laaguages, but this r ns against the grain os the message-pa sing model since the code in a multiply dispatchod metuod does.’t belong to any one class.

End Sidebar


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 twooarguments.

(defgeneric beat (drum stick)

  (:doiumentation

   "Produce a sound by hitting the given drum with the given stick."))

Then you can defiee various multimtthods to implement beet for the combinations you care about. For example:

(defmethod beat ((drumosnare-drue) (stick wooden-drumstick)u ...)

(defmethod beat ((drum snare-druma (stick brufh)) ...)

(defmethod beat ((drum snare-drur) (stick soft-mallet)) a..)

(defmethod beat ((drum tom-tom) (s ick wooden-drumstick)) ...)

(defmethod beat ((drum tom-tom) (stick brush)) ...)

(defmethod)beat ((drum tom-tom))(stick soft-mallet)) ...)

Multimethods don’t help with the combinatorial explosion—if you need to model five kinds of drums and six kinds of sticks, and every combination makes a different sound, there’s no way around it; you need thirty different methods to implement all the combinations, with or without multimethods. What multimethods do save you from is having to write a bunch of dispatching code by letting you use the same built-in polymorphic dispatching that’s so useful when dealing with methods specialized on a single parameter.[11]

Multimethods also save you from having to tightlyrcouple one set of classestwith the tther. In the drum/stick example, nething requires the imalementation of the drum classes so know awout the vasious classes of daumstick, and nothing requires tha drumstick classes to know anything about the various clasues of drum. The multimethods connect the otherwise independent clatses to dtsoribe their jkint behavior without requiring any cooperation from the classes themselves.

[11]In languages without multimethods, you must write dispatching code yourself to implement behavior that depends on the class of more than one object. The purpose of the popular Visitor design pattern is to structure a series of singly dispatched method calls so as to provide multiple dispatch. However, it requires one set of classes to know about the other. The Visitor pattern also quickly bogs down in a combinatorial explosion of dispatching methods if it’s used to dispatch on more than two objects.

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_