您想要完成的任务虽然令人钦佩,但在大多数情况下并不适合 Java。但在我开始之前……
Java 8 向接口添加了默认方法!您可以根据接口中的其他方法定义默认方法。这已经可用于抽象类。
public interface Animal {
public void speak();
public default void jump() {
speak();
System.out.println("...but higher!");
}
}
但最终,您将必须为每种类型提供功能。我没有看到添加新方法和创建访问者类或部分函数之间有很大区别。这只是一个位置问题。您想按操作或对象组织代码吗? (功能或面向对象、动词或名词等)
我想我想要表达的观点是,Java 代码是按“名词”组织的,其原因不会很快改变。
访问者模式和静态方法可能是通过操作组织事物的最佳选择。然而,我认为当访问者并不真正依赖于他们访问的对象的确切类型时,他们才是最有意义的。例如,动物访客可能用于让动物说话然后跳跃,因为所有动物都支持这两件事。跳跃访客对我来说没有多大意义,因为这种行为本质上是针对每种动物的。
Java 使真正的“动词”方法有点困难,因为它根据参数的编译时类型选择要运行的重载方法(见下文和根据参数的真实类型选择重载方法 https://stackoverflow.com/questions/1572322/overloaded-method-selection-based-on-the-parameters-real-type)。方法仅根据类型动态调度this
。这就是继承是处理此类情况的首选方法的原因之一。
public class AnimalActions {
public static void jump(Animal a) {
a.speak();
System.out.println("...but higher!");
}
public static void jump(Bird b) { ... }
public static void jump(Cat c) { ... }
// ...
}
// ...
Animal a = new Cat();
AnimalActions.jump(a); // this will call AnimalActions.jump(Animal)
// because the type of `a` is just Animal at
// compile time.
您可以通过使用来解决这个问题instanceof
以及其他形式的反思。
public class AnimalActions {
public static void jump(Animal a) {
if (a instanceof Bird) {
Bird b = (Bird)a;
// ...
} else if (a instanceof Cat) {
Cat c = (Cat)a;
// ...
}
// ...
}
}
但现在您只需执行 JVM 旨在为您完成的工作。
Animal a = new Cat();
a.jump(); // jumps as a cat should
Java 有一些工具可以更轻松地向大量类添加方法。即抽象类和默认接口方法。 Java 专注于根据调用方法的对象来调度方法。如果你想编写灵活且高性能的 Java,我认为这是你必须采用的一种习惯用法。
P.S.因为我是That Guy™ 我将介绍 Lisp,特别是 Common Lisp 对象系统 (CLOS)。它提供了基于所有参数进行调度的多种方法。这本书实用 Common Lisp甚至提供与 Java 有何不同的示例 http://www.gigamonkeys.com/book/object-reorientation-generic-functions.html#multimethods.