如果这是不合适的,请告诉我(特别是Programmers.SE是否会更好地解决这个问题。)
好的。所以我有很多'特征',我目前正在表达为接口。让我们称它们为“可更新”和“可破坏”。将它们表示为接口有一个缺点,我无法在所有“可破坏”组件之间共享行为;另一方面,将这些表示为抽象类意味着我不能混合和匹配而不将混合特征明确定义为另一个抽象类(“UpdateableAndDestructible”),而且这感觉就像滥用抽象类功能一样。但是,如果没有更清晰的方法来解决这个问题,我可能最终会这样做。
对于这个难题,纯Java解决方案有哪些选择?我是否有可能描述共享行为,然后按照我认为合适的方式进行混合和匹配,而不必明确描述我将要使用的每个排列?
答案 0 :(得分:6)
也许你可以通过使用混合接口和默认实现来实现目标。
像:
public interface Updatable {
void updated();
}
public interface Loadable {
void load();
}
public class DefaultUpdatable implements Updatable {
...
}
public class DefaultLoadable implements Loadable {
...
}
public class SomeObject implements Updatable, Loadable {
private final Updatable updatable = new DefaultUpdatable();
private final Loadable loadable = new DefaultLoadable();
public void load() {
this.loadable.load();
}
public void updated() {
this.updatable.updated();
}
}
仍然很嘈杂,可能没有您想要的那么灵活,但可能比使用UpdatableAndDestructable更清洁。
答案 1 :(得分:5)
我不认为这个问题有一个漂亮的解决方案,但可能有一些可行的解决方案取决于你多少鄙视样板。
您可以将特征定义为另一个类+接口,它将实例对象作为第一个参数。并且它们实现了与您想要具有特征的类的接口。然后创建调用特征impl上方法的存根方法。
public class MyClass implements MyTrait {
@Override
public void doSomething() {
MyTraitImpl.doSomething(this);
}
}
然后是特质本身:
public interface MyTrait {
public void doSomething();
}
public class MyTraitImpl {
public static void doSomething(MyTrait obj) {
// do something with obj
}
}
正如Ernest Friedman-Hill所说,Scala为你做了这件事(据我所知,这就是它在JVM上实现特征的方式)。
答案 2 :(得分:4)
我知道你说的是“纯Java”,但这是Scala做得很好的事情。 Java语言本身的局限性是人们采用其他JVM语言的强大动力......
答案 3 :(得分:1)
如果您考虑使用lombok作为纯Java,可以使用@Delegate
这样简化您的生活:
public class SomeObject implements Updatable, Loadable {
@Delegate private final Updatable updatable = new DefaultUpdatable();
@Delegate private final Loadable loadable = new DefaultLoadable();
}