【问题标题】:java traits or mixins pattern?java trait 还是 mixins 模式?
【发布时间】:2010-09-20 18:12:05
【问题描述】:

有没有办法在 java 中模拟 mixins 或 trait?基本上,我需要一种方法来进行多重继承,这样我就可以将通用的业务逻辑添加到多个类中

【问题讨论】:

    标签: java mixins traits


    【解决方案1】:

    今天你的对象纯粹主义者在激荡吗?

    您认为您可以使用一点面向复合的编程吗?

    那么,先生,您正在寻找Apache Polygene(以前的 Qi4J 或 Zest);)

    【讨论】:

    • 它支持特征还是只支持混入? IE。当两个具有相同签名的方法发生冲突时,是一个胜出,还是显示为编译器错误并为您提供解决冲突的方法?
    • @NeilTraft 方法解析是可预测的,并且基于声明顺序,请参阅qi4j.org/_core.html#core-api-mixin
    【解决方案2】:

    从 Java-8 开始,添加了默认接口方法。这与 Java 中接口的多重继承一起应该允许某种混合。显然,接口必须独立运行。所以,会有很大的限制。

    【讨论】:

      【解决方案3】:

      我会将所有业务逻辑封装到一个新类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。

      【讨论】:

      【解决方案4】:

      您可以利用接口允许嵌套类(自动为公共静态)的事实来保持接口方法的默认实现封装在接口本身中。 IE。将 Alex B 示例的 BusinessLogic 类移到界面内。

      这类似于 Scala 为特征生成 JVM 代码的方式,如 How are Scala traits compiled into Java bytecode? 此处所述

      执行此操作时,示例变为:

      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 将包含“虚拟扩展方法”,这将更容易启用。
      【解决方案5】:

      使用 CGLib/javassit 在 java 中实现简单的 mixin/traits 支持非常容易。 你可以看看 here 的小例子。 可能会找到更完整、可立即使用的解决方案:here

      【讨论】:

        【解决方案6】:

        QI4J 允许您使用 mixins

        【讨论】:

          【解决方案7】:

          不是你想要的方式。 Effective Java 建议您“优先组合而不是继承”。这意味着您将通用逻辑移至其他类并委托。这就是你如何解决java中缺乏多重继承的问题。

          【讨论】:

            【解决方案8】:

            Java 对多重继承的回答是能够实现多个接口。当然,这意味着您将获得方法声明,而不是逻辑。

            您可以尝试通过组合来模拟 mixin:您的 Java 类可以定义代表其他执行某些常见业务逻辑的类的成员变量。

            在设计 Java 类时,我没有发现缺乏 C++ 风格的多重继承来抑制我的架构设计。你会找到一种方法来实现你想做的事情。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-03-16
              • 1970-01-01
              • 2011-11-28
              • 2012-07-08
              • 1970-01-01
              • 2014-04-29
              • 2013-03-04
              • 2010-12-24
              相关资源
              最近更新 更多