在 Java 中实现 Mixin? [关闭]

Posted

技术标签:

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

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

【问题讨论】:

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

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

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

【讨论】:

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

在 Java 中伪造 mixins:http://jonaquino.blogspot.com/2005/07/java-mixin-pattern-or-faking-multiple.html

【讨论】:

【参考方案3】:

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

【讨论】:

【参考方案4】:

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

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

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

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

您可以为此使用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) 

【讨论】:

【参考方案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 可能值得一看。

【讨论】:

对不起,我没有看到你的答案,但你可以使用 AspectJ:***.com/questions/7403321/…【参考方案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 提供此功能。我的第一个选择是使用本文中显示的示例:

Mixins in Pure java

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

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

Jackson MixIn Annotations

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

Java 8: You now have mixins?

使用虚拟扩展方法,这需要努力'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

【讨论】:

以上是关于在 Java 中实现 Mixin? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 C# 中实现 mixins?

如何使用 Java Spring 在 MySql 中实现多租户 [关闭]

在 Java 中实现单例模式的有效方法是啥? [关闭]

如何在 C++ 中实现方法返回类似 Java 中的对象 [关闭]

C++中多态是怎样实现的?

在 webview 片段中实现后退按钮