有没有办法在java中模拟mixins或trait?基本上,我需要一种方法来进行多重继承,这样我就可以将通用业务逻辑添加到几个类中
8 回答
不是你想要的方式。Effective Java建议您“优先组合而不是继承”。这意味着您将通用逻辑移至其他类并委托。这就是你如何解决java中缺乏多重继承的问题。
我会将所有业务逻辑封装到一个新类BusinessLogic
中,并让每个需要BusinessLogic
调用该类的类。如果您需要为调用 的类提供单一根层次结构BusinessLogic
,则还必须创建一个接口(BusinessLogicInterface
?)
在伪代码中:
interface BusinessLogicInterace
{
void method1();
void method2();
}
class BusinessLogic implements BusinessLogicInterface
{
void method1() { ... }
void method2() { ... }
}
class User
extends OtherClass
implements BusinessLogicInterface
{
BusinessLogic logic = new BusinessLogic();
@Override
void method1() { logic.method1(); }
@Override
void method2() { logic.method2(); }
}
这不是解决缺乏多重继承的最漂亮的实现,当接口有很多方法时它变得非常麻烦。最有可能的是,您需要尝试重新设计代码以避免需要 mixin。
Java 对多重继承的回答是能够实现多个接口。当然,这意味着您将获得方法声明,但不会获得逻辑。
您可以尝试通过组合来模拟 mixin:您的 Java 类可以定义代表其他执行某些常见业务逻辑的类的成员变量。
在设计 Java 类时,我没有发现缺乏 C++ 风格的多重继承来抑制我的架构设计。你会找到一种方法来实现你想做的事情。
QI4J 允许你使用 mixins
您可以利用接口允许嵌套类(自动为公共静态)的事实来保持接口方法的默认实现封装在接口本身中。即把Alex B 的例子的BusinessLogic 类移到接口里面。
这类似于 Scala 为特征生成 JVM 代码的方式,如此处所述如何将 Scala 特征编译为 Java 字节码?
这样做时,示例变为:
interface BusinessLogicInterface {
void method0();
class DefaultImpl {
private DefaultImpl() {
}
public static void method1(BusinessLogicInterface self) { ... }
public static void method2(BusinessLogicInterface self) { ... }
}
void method1();
void method2();
}
class User extends OtherClass implements BusinessLogicInterface {
@Override
void method0() { ... }
@Override
void method1() { BusinessLogic.defaultImpl.method1(this); }
@Override
void method2() { BusinessLogic.defaultImpl.method2(this); }
}
请注意,我们将接口类型的对象作为“self”参数传递。这意味着业务逻辑可以使用其他抽象方法(method0)。这对于使用彼此正交的抽象方法和可以根据这些正交方法实现的实用程序“扩展”方法来创建特征非常有用。
缺点是每个接口都必须复制/粘贴样板委托代码。另一个在 Java 中经常使用的没有这个缺点的模式(但具有较少的内聚性和较少的 OO 方式来调用方法)是创建一个具有复数名称的类作为包含静态方法的接口,这在 Collections 实用程序类中使用。
从 Java-8 开始,添加了默认接口方法。这与 Java 中接口的多重继承一起应该允许某种混合。显然,接口必须独立运行。所以,会有很大的限制。