Multiple Dispatch & Static Overload.
It is NOT true that all OOP languages require the cumbersome double-dispatch pattern to implement binary operatoins in a full OOP style. Languages with multimethods, also known as multiple dispatch, provide more intuitive solutions.
支持 multiple dispatch 的语言允许在类中声明多个同名方法。举例来说,在允许 multiple dispatch 的语言中,在 Int, MyString, 与 MyRational 类中均可定义三个名为 add_values 的方法;也就是说程序中将会有 3 * 3 = 9 个名为 add_values 的方法,分别对应 9 个 cases。
Each add_values method would indicate the class it expects for its argument. Then e1.eval.addvalues e2.eval would pick the right one of the 9 by, at run-time, considering the class of the result of e1.eval and the class of the result of e2.eval.
Ruby, Java, C#, C++ 等语言采用的均是 dynamic single dispatch: the method-lookup rules involve the run-time class of the receiver (the object whose method we are calling, or self), not the run-time class of the argument(s).
而 dynamic multiple dispatch 不仅仅考虑 receiver 的类,它将根据多个对象 (当然包括传入的参数) 的类来选择需要被调用的方法。因此可以说 multiple dispatch is “even more dynamic dispatch”.
Java 与 C++ 这样的 statically typed languages 不支持 multiple dispatch,但它们允许在类中定义同名方法,并通过我们所声明的实参类型 (types) 来选择调用的方法。这一 semantic 被称为 static overloading。
| Static Overloading | Multiple Dispatch | |
|---|---|---|
| languages | statically typed OOP | dynamically typed OOP |
| argument dependence | types of arguments at compile-time | run-time class of the result of evaluating the arguments |
| receiver dependence | run-time class of receiver (odd hybrid?) | run-time class of receiver |
| double dispatch | does not avoid double dispatch | simplify cumbersome double dispatch |
在 (dynamic) single dispatch 根据 receiver 的 run-time class 选择调用的方法这一基础上,multiple dispatch 根据参数的 run-time class 进一步选择,static overloading 根据参数的 types 进一步选择。
但 multiple dispatch 能够在某种程度上简化笨重的 double dispatch technique;static overloading 则无法做到这一点,当需要使用 double dispatch 时还是无法避免。