在Java中实现Mixin?

时间:2009-02-25 19:29:23

标签: java mixins

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

18 个答案:

答案 0 :(得分:21)

您可以使用CGLIB。类Mixin能够从多个接口/对象委托生成动态类:

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) 

答案 1 :(得分:13)

我会说只使用对象组合。每次想要引入新功能时,将另一个对象作为成员组成类。如果要创建所有相同类型的混合类,可以使用数组作为成员对象,其中每个元素都由其他所有元素组成,并且可以调度到特定元素。

答案 2 :(得分:13)

默认方法

我知道Java 6的问题,但在Java 8中,我们将有一个相当不错的选择:default methods

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

只要你的mixin不需要状态,你就可以在界面中编写代码。然后,您的班级可以根据需要实现尽可能多的接口,并you've got mixins

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

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

答案 3 :(得分:8)

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

编辑:由于有关接口的评论:关于mixins的一个很酷的事情是你可以在不编写组合代码的情况下组合它们。使用接口,您必须自己实现组合的功能(除了可以扩展的一个类)!

答案 4 :(得分:7)

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

优点:

  • 非常容易
  • 你可以'混合'尽可能多的静态导入

缺点:

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

示例:

import static my.package.MyHelperUtility.methodDefinedInAnotherClass;

public class MyNormalCode {
    public void example() {
        methodDefinedInAnotherClass();
    }
}

答案 5 :(得分:5)

从某种意义上说,Ruby混合相当于Java抽象类,不,你不能在Java中实现混合。你可以通过使用接口来完成,因此在你的混合中绝对没有定义任何代码,但是你不能直接实现与Ruby混合中相同的行为。

答案 6 :(得分:5)

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

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

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

有关概述,请参阅http://www.qi4j.org/state-modeling.html

在Qi4j中,只有Mixins有状态。约束/关注/ SideEffects不能有状态(如果他们需要参考私人混音)。

要在Qi4j中定义合成,可以在类型本身上进行结构化处理,也可以在创建运行时模型时的引导时进行。

结构上;

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

开机时;

public interface Car
{}

public class CarModuleAssembler implements Assembler { public void assemble( ModuleAssembly module ) { module.entities( Car.class ) .withMixins( PetronEngineMixin.class, FourWheelsMixin.class ); } }

然而,这只是触及Qi4j中的特征表面。

答案 7 :(得分:4)

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

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

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

答案 8 :(得分:4)

答案 9 :(得分:2)

答案 10 :(得分:2)

不确定您正在寻找的mixins的哪些功能,但很多功能都可以使用装饰器模式完成。

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

答案 11 :(得分:2)

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

答案 12 :(得分:1)

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

答案 13 :(得分:1)

我正在探索为Java 7提供这个。我的第一个剪辑是使用本文中显示的示例:

它应该与java 6一起使用,它类似于上面的其他注入选项。基于我在C#和Ruby中使用Mixins的经验,你应该专注于实现mixins,而不仅仅是模仿或伪造它。

另一个模型是与Jackson一起使用的模型:

如果您可以使用新的Java 8版本,请说明您是否处于预发布模式,这可能有所帮助。

使用虚拟扩展方法,这需要努力 '混入。所以在我看来它还处于早期阶段,我更喜欢第一个链接提供的更清晰的方法(或类似方法)。

答案 14 :(得分:1)

我相信this可能会回答你的问题......虽然我还不完全sure I understand what a mixin is yet...

答案 15 :(得分:0)

术语'Mixin'在面向方面的编程运动中不等同于Java术语'方面'吗? AspectJ可能值得一看。

答案 16 :(得分:0)

对旧问题的回答。

我看了一下Apache Zest。也许只是我,但我发现这些例子有点麻烦。我无法理解这一点。另一种选择可能是对象团队。

但我建议你看一下这个回购:

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!"

答案 17 :(得分:0)

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

https://github.com/literadix/JavaMixins