Implement Mixin In Java? [closed]

2019-01-07 07:28发布

问题:

Using Java 6, how can I implement a mixin? It is very easy and possible in Ruby. How can I get similar in Java?

回答1:

You could use CGLIB for that. The class Mixin is able to generate a dynamic class from several interfaces / object delegates:

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) 


回答2:

I'd say just use object composition. Every time you want to throw in new functionality, compose another object into the class as a member. If you want to make all of your mixed-in classes of the same type, you can use an array as a member object where each element is composed with all of the others, and you can dispatch to a particular element.



回答3:

Default Methods

I know the question said Java 6, but in Java 8 we'll have a pretty decent alternative: default methods.

We'll be able to add 'default' implementations of interface methods, so we can add new methods without breaking every class that implements the interface.

As long as your mixin doesn't need state, you can write code in an interface. Then your class can implement as many of these interfaces as it wants and boom, you've got mixins.

Is this an abuse of the system? A little bit, but it doesn't get into any multiple inheritance issues because there's no state.

Of course, that's also the biggest disadvantage with this approach.



回答4:

Since Java only supports single inheritance, that is not possible. Have a look at WP: Mixin.

EDIT: Because of the comments about interfaces: The cool thing about mixins is that you can combine them without writing the combination's code. With interfaces you have to implement the combination's functionality yourself (except one class you can extend)!



回答5:

The simplest approach is to use static imports. It allows for code reuse that 'looks' like it's part of the class, but is really defined elsewhere.

Pros:

  • really easy
  • you can 'mixin' as many static imports as you like

Cons:

  • the static methods won't have access to 'this', so you'd have to pass it in manually
  • no state: your static methods can't have their own instance fields. They can only define their own static fields, which are then shared by any object calling the static method.
  • can't define public methods on the client class (the one with code being mixed into it). In Ruby, importing a mixin will actually define those public methods as public methods on your class. In Java, inheritance would be a better solution in this case (assuming you don't need to extend multiple classes)

Example:

import static my.package.MyHelperUtility.methodDefinedInAnotherClass;

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


回答6:

In the sense that a Ruby mix-in is the equivalent of a Java abstract class, no, you cannot implement a mix-in in Java. You can come close by using interfaces and thus defining absolutely no code in your mix-in, but you cannot directly achieve the same behavior as in a Ruby mix-in.



回答7:

UPDATE: Qi4j is now Apache Polygene, https://polygene.apache.org

Qi4j's definition of Mixins are probably quite unique, as it doesn't start with a base class. By going to that extreme, a whole new paradigm of how applications are built up emerges, and we call that Composite Oriented Programming. The Composite is the 'object' equivalent and not only are Mixins wired together, but also Constraints (validation), Concerns (around advice) and SideEffects (can't alter the method outcome).

So I think Qi4j has a very strong Mixin story to tell. Mixins can be 'typed' or 'generic', they can be public (accessible outside the composite) or purely private (within the Composite). Qi4j strongly defines what Properties are, and goes on to have built-in persistence, which doesn't leak the storage implementation into your domain (caveat; Qi4j leaks to your domain). And once persisted entities enters the picture, strong definition of a Associations are also required (and included in Qi4j).

See http://www.qi4j.org/state-modeling.html for a good overview.

In Qi4j, ONLY Mixins have state. Constraints/Concerns/SideEffects can't have state (if they do they need to referens a private mixin).

To define a composite in Qi4j, it is possible to either do it structurally on the types themselves, OR at bootstrap time when the runtime model is created.

Structurally;

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

At boot time;

public interface Car
{}

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

Yet, this is just touching on the surface of the features in Qi4j.



回答8:

Take a peek at http://code.google.com/p/javadude/wiki/AnnotationsMixinExample

It's using a set of annotations I've created.

Note: I'm working on a major update to the annotations, which includes some API breakage. I plan to release a new version in the next few weeks.



回答9:

just ran across: http://www.berniecode.com/blog/2009/08/16/mixins-for-java/



回答10:

Faking mixins in Java: http://jonaquino.blogspot.com/2005/07/java-mixin-pattern-or-faking-multiple.html



回答11:

You can do Mixins with Java now (ie 5,6,7) using AspectJ ITDs. Java 8 of course will add better capabilities with its defender methods.



回答12:

Not sure exactly what features from mixins you're looking for but much of it can be done using the decorator pattern.

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



回答13:

I believe this may answer you question...although I'm not completely sure I understand what a mixin is yet...



回答14:

Yes, the most simple and convinient way to implement mixins apporoach in Java - is to use static import from some class which contains static methods.



回答15:

I am exploring providing this for Java 7. My first cut will be to use the example shown in this article:

  • Mixins in Pure java

It ought to work with java 6, it is similar to the other injection options above. Based on my experience with Mixins in C# and Ruby, you should aim to implement mixins, not just emulate or fake it.

Another model, is the one used with Jackson:

  • Jackson MixIn Annotations

If you can use the new Java 8 release, say if you are in pre-release mode, that might help.

  • Java 8: You now have mixins?

Using Virtual Extension method, which requires effort to 'be-a' mixin. So in my mind it is still early days and I prefer the cleaner looking approach (or similar) offered by the first link.



回答16:

Is the term 'Mixin' not equivalent to the Java term 'aspect' in the aspect-oriented programming movement? AspectJ is probably worth a look.



回答17:

An answer to an old question.

I took a look at Apache Zest. Maybe it was just me but I find the examples a little bit cumbersome. And I couldn't quite get the point. Another alternative may be object teams.

But I suggest you may take a look at this repo:

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

It might partially cover what you want to do. It seems simple.

Here is an example:

Defining the interface for the roles:

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

public interface Monkey {String hello(); String eat();}

Defining rigid type 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";
}
}

Defining class role Bonobo...

public class Bonobo implements Monkey{
public Bonobo() {}

@Override
public String hello(){
    return "Ugauga";
}

@Override
public String eat() {
    return "Nhamnham";
}

}

Defining class role Portuguese...

@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!";
}

}

Running the test...

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

Would print...

"Hey there"
"Dance modified!"


回答18:

Please have a look of my small demonstration project how to create mixins in pure java using cglib. Mainly it is just a call to a proxy generator. This is ally. The example contains an junit test case demonstrating how to instantinate the proxy.

https://github.com/literadix/JavaMixins



标签: java mixins