【问题标题】:Ways to achieve effective Java traits?实现有效 Java 特征的方法?
【发布时间】:2011-08-22 18:44:20
【问题描述】:

请让我知道这是否不合适(特别是 Programmers.SE 或其他内容是否更适合该问题。)

好的。所以我有许多“特征”,我目前正在将它们表达为接口。我们称它们为“可更新的”和“可破坏的”。将它们表示为接口的缺点是我无法在所有“可破坏”组件之间共享行为;另一方面,将这些表示为抽象类意味着如果不将混合特征明确定义为另一个抽象类(“UpdateableAndDestructible”),我就无法混合和匹配,而且这在那时感觉就像是对抽象类功能的滥用。但是,如果没有更清洁的方法来处理这个问题,我可能最终会这样做。

就这个难题的纯 Java 解决方案而言,我有哪些选择?我是否可以描述共享行为,然后在我认为合适的情况下进行混合和匹配,而不必明确描述我将使用的每个排列?

【问题讨论】:

  • 您正在描述 mixins - 如果您正在搜索,这可能是一个有用的术语。

标签: java interface abstract-class traits


【解决方案1】:

也许您可以通过混合使用接口和默认实现来实现目标。

喜欢:

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 并被接受,这是处理问题的明智方法。 (顺便说一句,在调查这个问题时,我发现了许多有用的框架,比如 Guice,它们让使用这种逻辑变得不那么痛苦。)
【解决方案2】:

我认为这个问题没有一个很好的解决方案,但可能有一些可行的解决方案,具体取决于您对样板的鄙视程度。

您可以将 trait 定义为另一个类 + 接口,它将实例对象作为第一个参数。他们使用您想要具有特征的类实现接口。然后创建调用 trait 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 上实现特征的方式)。

【讨论】:

    【解决方案3】:

    我知道你说的是“纯 Java”,但 Scala 做得很好。 Java 语言本身的局限性是人们采用其他 JVM 语言的强大驱动力...

    【讨论】:

      【解决方案4】:

      如果您考虑将lombok 用作纯Java,您可以像这样使用@Delegate 来简化您的工作:

      public class SomeObject implements Updatable, Loadable {
          @Delegate private final Updatable updatable = new DefaultUpdatable();
          @Delegate private final Loadable loadable = new DefaultLoadable();
      }
      

      【讨论】:

        猜你喜欢
        • 2013-10-31
        • 1970-01-01
        • 1970-01-01
        • 2019-12-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多