【问题标题】:Implement Mixin In Java? [closed]在 Java 中实现 Mixin? [关闭]
【发布时间】:2010-10-09 21:40:44
【问题描述】:

使用 Java 6,我如何实现 mixin?这在 Ruby 中非常简单且可行。我怎样才能在 Java 中得到类似的东西?

【问题讨论】:

  • 你是说mixin?通常用多重继承完成的那种?
  • mixin 也可以看成是一个实现了方法的接口。根据定义,这将是一个 Java 抽象类。
  • 在 Java 8 中请参考@Brad Cupit 的答案:stackoverflow.com/a/13992641/5290519

标签: java mixins


【解决方案1】:

由于 Java 只支持单继承,这是不可能的。看看WP: Mixin

编辑:由于关于接口的 cmets:mixin 的酷之处在于您可以将它们组合起来而无需编写组合代码。使用接口你必须自己实现组合的功能(除了一个你可以扩展的类)!

【讨论】:

  • 据说可以使用接口?
  • 使用接口有一半可能。
  • Java支持动态类构建,所以是可以的。
【解决方案2】:
【解决方案3】:

从某种意义上说,Ruby mix-in 等同于 Java 抽象类,不,您不能在 Java 中实现 mix-in。您可以通过使用接口来接近,因此在您的混入中绝对不定义任何代码,但您不能直接实现与在 Ruby 混入中相同的行为。

【讨论】:

    【解决方案4】:

    看看http://code.google.com/p/javadude/wiki/AnnotationsMixinExample

    它使用了我创建的一组注释。

    注意:我正在对注释进行重大更新,其中包括一些 API 损坏。我计划在接下来的几周内发布一个新版本。

    【讨论】:

      【解决方案5】:

      我想说只使用对象组合。每次你想加入新功能时,将另一个对象作为成员组合到类中。如果你想让你的所有混合类都具有相同的类型,你可以使用一个数组作为成员对象,其中每个元素都由所有其他元素组成,你可以分派给一个特定的元素。

      【讨论】:

        【解决方案6】:

        您可以为此使用CGLIBMixin 类能够从多个接口/对象委托生成动态类:

        static Mixin    create(java.lang.Class[] interfaces,
                                java.lang.Object[] delegates)
        static Mixin    create(java.lang.Object[] delegates)
        static Mixin    createBean(java.lang.Object[] beans) 
        

        【讨论】:

          【解决方案7】:

          最简单的方法是使用静态导入。它允许代码重用“看起来”像是类的一部分,但实际上是在其他地方定义的。

          优点:

          • 真的很简单
          • 您可以“混合”任意数量的静态导入

          缺点:

          • 静态方法将无权访问 到“这个”,所以你必须通过它 手动输入
          • 无状态:您的静态方法不能有自己的实例字段。它们只能定义自己的静态字段,然后由调用静态方法的任何对象共享。
          • 无法在客户端类(其中混入了代码的类)上定义公共方法。在 Ruby 中,导入 mixin 实际上会将这些公共方法定义为类上的公共方法。在 Java 中,在这种情况下继承会是更好的解决方案(假设您不需要扩展多个类)

          例子:

          import static my.package.MyHelperUtility.methodDefinedInAnotherClass;
          
          public class MyNormalCode {
              public void example() {
                  methodDefinedInAnotherClass();
              }
          }
          

          【讨论】:

          • 请不要这样做。你的对象会很快变得精神分裂,见en.wikipedia.org/wiki/…。此外,使用静态方法组合对象会使它们难以测试。
          • 这只是一个实现细节;静态方法不会作为您的类上的方法公开。 “这个”没有混淆,所以我认为精神分裂症不适用,尽管读起来很有趣。
          • 我没有说清楚,抱歉。静态代码很难测试。精神分裂症问题不是关于静态代码,而是更多关于在不知道“this”的方法中丢失上下文。如果您的“混合”方法之一需要访问“this”,您的方法受对象精神分裂症的影响。
          • 我会说如果 mixin 必须有状态,那就有问题了。您将拥有mixinMethod(this,mixinState) 而不是mixinMethod(this),这有点精神分裂。
          【解决方案8】:

          刚刚遇到:https://blog.berniesumption.com/software/mixins-for-java/(Borken 链接已更新)

          【讨论】:

          • -1;整个 SE 不鼓励仅链接的答案。请提供链接信息的摘要。链接总是有可能删除其内容的关键部分,或者在最坏的情况下变成 404。
          【解决方案9】:

          是的,在 Java 中实现 mixins 方法最简单、最方便的方法是从包含静态方法的某个类中使用静态导入。

          【讨论】:

            【解决方案10】:

            在面向方面的编程运动中,术语“混合”是否不等同于 Java 术语“方面”? AspectJ 可能值得一看。

            【讨论】:

            【解决方案11】:

            更新:Qi4j 现在是 Apache Polygene,https://polygene.apache.org

            Qi4j 对 Mixins 的定义可能非常独特,因为它不是从基类开始的。通过走向这个极端,一个全新的应用程序构建范式出现了,我们称之为面向复合编程。 Composite 是“对象”等价物,不仅将 Mixins 连接在一起,而且还有 Constraints(验证)、Concerns(围绕建议)和 SideEffects(不能改变方法结果)。

            所以我认为 Qi4j 有一个非常强大的 Mixin 故事要讲。 Mixin 可以是“类型化的”或“通用的”,它们可以是公共的(可在组合外访问)或纯私有的(在组合内)。 Qi4j 强烈定义了属性是什么,并继续具有内置的持久性,它不会将存储实现泄漏到您的域中(警告;Qi4j 泄漏到您的域)。并且一旦持久化实体进入图片,还需要对关联的强定义(并包含在 Qi4j 中)。

            请参阅http://www.qi4j.org/state-modeling.html 以获得良好的概述。

            在 Qi4j 中,只有 Mixins 有状态。 Constraints/Concerns/SideEffects 不能有状态(如果有的话,它们需要引用私有 mixin)。

            要在 Qi4j 中定义组合,可以在类型本身的结构上进行,或者在创建运行时模型时在引导时进行。

            结构上;

            @Mixins({PetrolEngfineMixin.class, FourWheelsMixin.class})
            public interface Car extends HasEngine, HasWheels, EntityComposite
            {}
            

            在启动时;

            public interface Car
            {}

            公共类 CarModuleAssembler 实现汇编器 { 公共无效组装(ModuleAssembly 模块) { 模块实体(汽车类) .withMixins(PetronEngineMixin.class, FourWheelsMixin.class); } }

            然而,这只是涉及 Qi4j 中功能的表面。

            【讨论】:

              【解决方案12】:

              默认方法

              我知道问题是 Java 6,但在 Java 8 中我们会有一个相当不错的替代方案:default methods

              我们将能够添加接口方法的“默认”实现,因此我们可以添加新方法而不会破坏实现该接口的每个类。

              只要你的 mixin 不需要状态,你就可以在接口中编写代码。然后,您的类可以实现任意数量的这些接口并繁荣,you've got mixins

              这是对系统的滥用吗?一点点,但它不会涉及任何多重继承问题,因为没有状态。

              当然,这也是这种方法最大的缺点。

              【讨论】:

                【解决方案13】:

                您现在可以使用 Java(即 5、6、7)using AspectJ ITDs 进行 Mixins。 Java 8 当然会通过其防御方法添加更好的功能。

                【讨论】:

                • 防御者方法确实向前迈出了一大步。
                【解决方案14】:

                不确定您正在寻找 mixin 的哪些功能,但其中大部分可以使用装饰器模式完成。

                http://en.wikipedia.org/wiki/Decorator_pattern#Java

                【讨论】:

                  【解决方案15】:

                  我正在探索为 Java 7 提供此功能。我的第一个选择是使用本文中显示的示例:

                  它应该适用于 java 6,它类似于上面的其他注入选项。根据我在 C# 和 Ruby 中使用 Mixins 的经验,您应该致力于实现 mixins,而不仅仅是模拟或伪造它。

                  另一种模型,与Jackson一起使用的模型:

                  如果您可以使用新的 Java 8 版本,比如您处于预发布模式,那可能会有所帮助。

                  使用虚拟扩展方法,这需要努力'be-a' mixin。所以在我看来,这还为时尚早,我更喜欢第一个链接提供的更简洁的方法(或类似方法)。

                  【讨论】:

                    【解决方案16】:

                    一个老问题的答案。

                    我查看了 Apache Zest。也许只有我一个人,但我发现这些例子有点麻烦。我不能完全理解这一点。另一种选择可能是对象团队。

                    但我建议你可以看看这个 repo:

                    https://github.com/Mashashi/javaroles/

                    它可能部分涵盖了您想要做的事情。看起来很简单。

                    这是一个例子:

                    为角色定义接口:

                    public interface Human {
                    String hello(); 
                    String die(String age);  
                    String eat();
                    String dance();
                    }
                    
                    public interface Monkey {String hello(); String eat();}
                    

                    定义刚性类型 AnimalRoles...

                    public class AnimalRoles implements Human, Monkey{
                    
                    public static final String HALLO = "Default hallo";
                    public static final String DIE = "Default they kill me...";
                    public static final String EAT = "Default eat...";
                    
                    @ObjectForRole public Human human;
                    
                    @ObjectForRole public Monkey monkey;
                    
                    public AnimalRoles(Human human, Monkey monkey){
                        this.human = human;
                        this.monkey = monkey;
                        if(this.human!=null){
                            ((Portuguese)this.human).core = this;
                        }
                    }
                    
                    @Override
                    public String hello() {
                        return HALLO;
                    }
                    
                    @Override
                    public String die(String age) {
                        return DIE+age;
                    }
                    
                    @Override
                    @TurnOffRole
                    public String eat() {
                        return EAT;
                    }
                    
                    @Override
                    public String dance() {
                        return "Just dance";
                    }
                    
                    public String notInRole(){
                        return "Oh oh";
                    }
                    }
                    

                    定义类角色 Bonobo...

                    public class Bonobo implements Monkey{
                    public Bonobo() {}
                    
                    @Override
                    public String hello(){
                        return "Ugauga";
                    }
                    
                    @Override
                    public String eat() {
                        return "Nhamnham";
                    }
                    
                    }
                    

                    定义类角色葡萄牙语...

                    @RoleObject(types = { AnimalRoles.class })
                    public class Portuguese implements Human{
                    
                    public static final String HALLO = "Hey there";
                    public static final String DIE = "They killed me";
                    public static final String EAT = "Eating boiled pork now";
                    
                    public AnimalRoles core;
                    
                    public Portuguese() {}
                    
                    @Override
                    public String hello() {
                        return HALLO;
                    }
                    
                    @Override
                    public String die(String age) {
                        return DIE+age;
                    }
                    
                    @Override
                    public String eat() {
                        return EAT;
                    }
                    
                    @Override
                    public String dance() {
                        return core.dance()+" modified!";
                    }
                    
                    }
                    

                    运行测试...

                    new RoleRegisterComposition().registerRools();
                    AnimalRoles a = new AnimalRoles(new Portuguese(), new Bonobo());
                    System.out.println(a.hello());
                    System.out.println(a.dance());
                    

                    将打印...

                    "Hey there"
                    "Dance modified!"
                    

                    【讨论】:

                    • 上面提到的Qi4j在进入Apache时被命名为Apache Zest。后来改名为 Apache Polygene,以避免与 Eclipse Zest 项目的名称冲突。
                    【解决方案17】:

                    请看一下我的小演示项目如何使用 cglib 在纯 java 中创建 mixins。主要它只是对代理生成器的调用。这是盟友。该示例包含一个 junit 测试用例,演示如何实例化代理。

                    https://github.com/literadix/JavaMixins

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2015-08-01
                      • 2016-12-20
                      • 2010-12-21
                      • 2012-05-23
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多