记住 groovy 的方法查找是方法参数的动态类型化,而 java 是静态类型的,这个 groovy的特性叫做复合方法 Mult imethods。
列表 7.16 显示了两个方法,这两个方法都叫做 oracle,唯一不同的仅仅是参数的类型,它们通过相同的静态类型和不同的动态类型调用了 2 次。
![]()
参数 x 是 Object 静态类型和 Integer 动态类型,参数 y 是 Object 静态类型和 String 动态类型。
两个参数有相同的静态类型,两次都采用与 jav a 等价的将方法分派给 oracle(Object),由于 groovy 通过动态类型进行方法分派,oracle(String)的专门实现被用在第二中情况。
通过这种能力,你能通过适当的覆盖行为更好的避免重复的代码。考虑在列表 7.17 中 的 equals 方法的实现,覆盖的 Object 的缺省 equals 方法仅仅用在参数类型为 Equalizer 的情况。
![]()
当一个类型为 Equalizer 的对象被传递给 equals 方法的时候,专门的实现被使用。
当传递其他类型的对象时,在 Object.equals 的缺省实现方法被调用,这个方法仅仅检查对象的引用。
调用的 equals 方法能完全不知道差异,从一个调用者的角度看,它就像 equals(Equilizer)覆盖了 equals(Object),这在 java 中是办不到的,相反,一个 java 程序员也许像这样写:[code]public class Equalizer { // Java public boolean equals(Object obj)
{
if (obj == null) return false;
if (!(obj instanceof Equalizer)) return false; Equalizer w = (Equalizer) obj;
return true; // custom logic here
}
}
[/code]这是不适当的,因为覆盖 equals 方法的逻辑对于在 java 中每一个自定义类型都会重复,这是使用静态类型并且使用动态类型解决方法的另外一个例子。
注意:无论在什么地方使用 JAVA 的静态类型 Object,这样代码实际上丢失了静态类 型的长处,你不可避免的使用造型来找回类型,折中的方法是编译时类型安全。
这就是为什 么 JAVA 类型概念叫做弱静态类型:丢失了静态类型的优势,但也没有得到动态类型语言的优势如复合方法(multimethods)。
通过对比,在 groovy 中通过参数的动态类型进行方法的派发是单一的和一致的实现。