Implementar Mixin en Java?

Usando Java 6, ¿cómo puedo implementar un mixin ? Es muy fácil y posible en Ruby. ¿Cómo puedo obtener similar en Java?

Podría usar CGLIB para eso. La clase Mixin puede generar una clase dinámica a partir de varias interfaces / delegates de objeto:

 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) 

Yo diría que simplemente use la composición de objetos. Cada vez que desee agregar nuevas funciones, componga otro objeto en la clase como miembro. Si desea hacer todas las clases mixtas del mismo tipo, puede usar una matriz como objeto miembro donde cada elemento se compone con todas las demás, y puede enviar a un elemento en particular.

Métodos predeterminados

Sé que la pregunta es Java 6, pero en Java 8 tendremos una alternativa bastante decente: métodos predeterminados .

Podremos agregar implementaciones “predeterminadas” de métodos de interfaz, para que podamos agregar nuevos métodos sin romper todas las clases que implementen la interfaz.

Siempre que su mixin no necesite estado, puede escribir código en una interfaz. Entonces tu clase puede implementar tantas interfaces como quiera y auge, tienes mixins .

¿Es esto un abuso del sistema? Un poco, pero no entra en problemas de herencia múltiple porque no hay estado.

Por supuesto, esa es también la mayor desventaja con este enfoque.

Dado que Java solo admite herencia individual, eso no es posible. Eche un vistazo a WP: Mixin .

EDITAR : Debido a los comentarios sobre las interfaces: Lo bueno de los mixins es que puedes combinarlos sin escribir el código de la combinación. Con las interfaces, usted debe implementar la funcionalidad de la combinación usted mismo (¡excepto una clase que puede ampliar)!

El enfoque más simple es usar importaciones estáticas. Permite la reutilización de código que “parece” que es parte de la clase, pero está realmente definido en otra parte.

Pros:

  • realmente fácil
  • puedes mezclar tantas importaciones estáticas como quieras

Contras:

  • los métodos estáticos no tendrán acceso a ‘esto’, por lo que tendrías que pasarlo manualmente
  • no state: sus métodos estáticos no pueden tener sus propios campos de instancia. Solo pueden definir sus propios campos estáticos, que luego son compartidos por cualquier objeto que invoque el método estático.
  • no puede definir métodos públicos en la clase de cliente (la que tiene código mezclado). En Ruby, la importación de un mixin realmente definirá esos métodos públicos como métodos públicos en su clase. En Java, la herencia sería una mejor solución en este caso (suponiendo que no necesita extender varias clases)

Ejemplo:

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

En el sentido de que una mezcla de Ruby es el equivalente de una clase abstracta de Java, no, no puede implementar una mezcla en Java. Puedes acercarte usando interfaces y así definir absolutamente ningún código en tu mezcla, pero no puedes lograr el mismo comportamiento que en una mezcla de Ruby.

ACTUALIZACIÓN: Qi4j ahora es Apache Polygene, https://polygene.apache.org

La definición de Qi4j de Mixins es probablemente bastante única, ya que no comienza con una clase base. Al llegar a ese extremo, surge un nuevo paradigma de cómo se crean las aplicaciones, y lo llamamos Progtwigción Orientado a Compuestos. El Composite es el equivalente de ‘objeto’ y no solo se mezclan los Mixins, sino también las Restricciones (validación), las Preocupaciones (alrededor del consejo) y los Efectos secundarios (no pueden alterar el resultado del método).

Así que creo que Qi4j tiene una historia de Mixin muy fuerte para contar. Los mixins se pueden ‘escribir’ o ‘generics’, pueden ser públicos (accesibles fuera del compuesto) o puramente privados (dentro del compuesto). Qi4j define fuertemente qué propiedades son, y continúa teniendo persistencia incorporada, que no filtra la implementación de almacenamiento en su dominio (advertencia: Qi4j se filtra a su dominio). Y una vez que las entidades persistentes entran en escena, también se requiere una fuerte definición de Asociaciones (y se incluye en Qi4j).

Consulte http://www.qi4j.org/state-modeling.html para obtener una buena descripción general.

En Qi4j, SOLO los Mixins tienen estado. Restricciones / Preocupaciones / Efectos secundarios no pueden tener estado (si lo hacen, necesitan referens una mezcla privada).

Para definir un compuesto en Qi4j, es posible hacerlo estructuralmente en los tipos en sí, O en el momento de arranque cuando se crea el modelo de tiempo de ejecución.

Estructuralmente

 @Mixins ({PetrolEngfineMixin.class, FourWheelsMixin.class})
 interfaz pública Car extiende HasEngine, HasWheels, EntityComposite
 {}

En el momento del arranque;

 interfaz pública Coche
 {} 

clase pública CarModuleAssembler
implementa ensamblador
{
assembly público vacío (módulo Módulo de ensamblaje)
{
module.entities (Car.class)
.withMixins (PetronEngineMixin.class, FourWheelsMixin.class);
}
}

Sin embargo, esto solo está tocando en la superficie de las características en Qi4j.

Eche un vistazo a http://code.google.com/p/javadude/wiki/AnnotationsMixinExample

Está usando un conjunto de anotaciones que he creado.

Nota: Estoy trabajando en una actualización importante de las anotaciones, que incluye algunas roturas API. Planeo lanzar una nueva versión en las próximas semanas.

Ahora puede hacer Mixins con Java (es decir, 5,6,7) usando AspectJ ITD . Java 8, por supuesto, agregará mejores capacidades con sus métodos de defensa.

No estoy seguro exactamente de qué características de mixins está buscando, pero gran parte se puede hacer utilizando el patrón de decorador.

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

Creo que esto puede responderte pregunta … aunque no estoy del todo seguro de entender qué es una mixin aún …

Sí, la forma más sencilla y conveniente de implementar mixins apporoach en Java, es usar la importación estática de alguna clase que contenga métodos estáticos.

Estoy explorando proporcionar esto para Java 7. Mi primer corte será usar el ejemplo que se muestra en este artículo:

  • Mixins en Pure java

Debería funcionar con java 6, es similar a las otras opciones de inyección anteriores. En función de mi experiencia con Mixins en C # y Ruby, debes intentar implementar mixins, no solo emularlo o simularlo.

Otro modelo, es el que se usa con Jackson :

  • Anotaciones de Jackson MixIn

Si puede usar la nueva versión de Java 8, indique si está en modo de lanzamiento previo, eso podría ayudar.

  • Java 8: ¿Ahora tienes mixins?

Usando el método de extensión virtual, que requiere esfuerzo para ‘ ser-un ‘ mixin. Por lo tanto, en mi opinión, todavía es temprano y prefiero el enfoque más limpio (o similar) que ofrece el primer enlace.

¿El término “Mixin” no es equivalente al término de Java “aspecto” en el movimiento de progtwigción orientado a aspectos? AspectJ es probablemente digno de una mirada.

Una respuesta a una vieja pregunta.

Eché un vistazo a Apache Zest. Quizás fui solo yo, pero los ejemplos me resultan un poco engorrosos. Y no pude entender el punto. Otra alternativa pueden ser los equipos de objetos.

Pero sugiero que pueda echar un vistazo a este repository:

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

Puede cubrir parcialmente lo que quieres hacer. Parece simple.

Aquí hay un ejemplo:

Definiendo la interfaz para los roles:

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

Definición de tipo rígido 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"; } } 

Definición del rol de clase Bonobo …

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

Definición del rol de clase Portugués …

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

Ejecutando la prueba …

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

Imprimiría …

 "Hey there" "Dance modified!" 

Eche un vistazo a mi pequeño proyecto de demostración sobre cómo crear mixins en Java puro usando cglib. Principalmente es solo una llamada a un generador de proxy. Esto es aliado. El ejemplo contiene un caso de prueba junit que demuestra cómo instanciar el proxy.

https://github.com/literadix/JavaMixins