你试图完成的事情虽然令人钦佩,但在大多数情况下并不适合Java。但在我开始之前...
Java 8 为接口添加了默认方法!您可以基于接口中的其他方法定义默认方法。这已经可用于抽象类。
public interface Animal {
public void speak();
public default void jump() {
speak();
System.out.println("...but higher!");
}
}
但最终,您将不得不为每种类型的功能提供功能。我没有看到添加新方法和创建访问者类或部分函数之间的巨大差异。这只是一个位置问题。是否要按操作或对象组织代码?(函数式或面向对象,动词或名词等)
我想我想说的是,Java代码是由“名词”组织的,原因不会很快改变。
访客模式和静态方法可能是按操作组织事物的最佳选择。但是,我认为当访问者并不真正依赖于他们正在访问的对象的确切类型时,他们最有意义。例如,动物访客可能被用来让动物说话,然后跳跃,因为这两件事都得到了所有动物的支持。跳跃访客对我来说没有多大意义,因为这种行为本质上是针对每种动物的。
Java使真正的“动词”方法有点困难,因为它根据参数的编译时类型选择要运行的重载方法(请参阅下面的基于参数的实际类型的重载方法选择)。仅根据 的类型动态调度方法。这就是继承是处理这些类型情况的首选方法的原因之一。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,我认为这是你必须采用的一个成语。
附言因为我是那个家伙,™所以我要提出Lisp,特别是Common Lisp Object System(CLOS)。它提供了基于所有参数进行调度的多方法。《Practical Common Lisp》一书甚至提供了一个例子,说明它与Java有何不同。