Подтвердить что ты не робот

Внедрить Mixin в Java?

Использование Java 6, как я могу реализовать mixin? Это очень легко и доступно в Ruby. Как я могу получить подобное в Java?

4b9b3361

Ответ 1

Вы можете использовать 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) 

Ответ 2

Я бы сказал, просто использую композицию объекта. Каждый раз, когда вы хотите добавить новую функциональность, составьте еще один объект в классе как член. Если вы хотите создать все свои смешанные классы того же типа, вы можете использовать массив как объект-член, где каждый элемент состоит из всех остальных, и вы можете отправить его в определенный элемент.

Ответ 3

Так как Java поддерживает только одно наследование, это невозможно. Посмотрите WP: Mixin.

РЕДАКТИРОВАТЬ: из-за комментариев об интерфейсах: замечательная вещь о миксинах заключается в том, что вы можете комбинировать их без написания кода комбинации. С интерфейсами вы должны реализовать комбинационную функциональность самостоятельно (кроме одного класса, который вы можете расширить)

Ответ 4

Самый простой способ - использовать статический импорт. Это позволяет повторное использование кода, которое "выглядит" как часть класса, но действительно определено в другом месте.

Плюсы:

  • очень просто
  • вы можете "смешивать" столько статических импорта, сколько вам нравится

Минусы:

  • статические методы не будут иметь доступа до 'this', поэтому вам придется пройти его в ручном режиме
  • no state: ваши статические методы не могут иметь свои собственные поля экземпляра. Они могут определять только свои собственные статические поля, которые затем разделяются любым объектом, вызывающим статический метод.
  • не может определять общедоступные методы в классе клиента (тот, в котором он смешивается с кодом). В Ruby импорт mixin фактически определит эти общедоступные методы как общедоступные методы в вашем классе. В Java наследование будет лучшим решением в этом случае (если вам не нужно расширять несколько классов)

Пример:

import static my.package.MyHelperUtility.methodDefinedInAnotherClass;

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

Ответ 5

Я знаю вопрос, который сказал Java 6, но в Java 8 у нас будет довольно приличная альтернатива: методы по умолчанию.

Мы сможем добавить "стандартные" реализации методов интерфейса, поэтому мы можем добавлять новые методы, не нарушая каждый класс, реализующий интерфейс.

Пока ваш миксин не нужен, вы можете написать код в интерфейсе. Тогда ваш класс может реализовать столько интерфейсов, сколько захочет и бум, у вас есть mixins.

Это злоупотребление системой? Немного, но он не попадает ни в какие множественные проблемы наследования, потому что нет состояния.

Конечно, это также самый большой недостаток этого подхода.

Ответ 6

В том смысле, что Ruby mix-in является эквивалентом абстрактного класса Java, нет, вы не можете реализовать смешение в Java. Вы можете приблизиться с помощью интерфейсов и, таким образом, не указывать абсолютно никакого кода в своем микшировании, но вы не можете напрямую достичь того же поведения, что и в Ruby mix-in.

Ответ 7

Взгляните на http://code.google.com/p/javadude/wiki/AnnotationsMixinExample

Он использует набор аннотаций, которые я создал.

Примечание. Я работаю над основным обновлением аннотаций, которое включает в себя некоторые поломки API. Я планирую выпустить новую версию в ближайшие несколько недель.

Ответ 9

UPDATE: Qi4j теперь является полигоном Apache, https://polygene.apache.org

Qi4j определение Mixins, вероятно, совершенно уникально, поскольку оно не начинается с базового класса. Переходя к этой крайности, возникает совершенно новая парадигма создания приложений, и мы называем это композитно-ориентированным программированием. Composite является эквивалентом "объекта", а не только Mixins, соединенным вместе, но также ограничениями (валидацией), проблемами (вокруг совета) и SideEffects (не может изменить результат метода).

Итак, я думаю, что у Qi4j есть очень сильная история Mixin. Микшины могут быть "типизированы" или "родовыми", они могут быть общедоступными (доступны вне композитных) или чисто частными (внутри Composite). Qi4j сильно определяет, какие свойства есть, и продолжает иметь встроенную персистентность, которая не просачивает реализацию хранилища в ваш домен (caveat; Qi4j утечки в ваш домен). И как только сохраняющиеся сущности входят в картину, также требуется сильное определение ассоциаций (и включено в Qi4j).

Для хорошего обзора см. http://www.qi4j.org/state-modeling.html.

В Qi4j ТОЛЬКО микшины имеют состояние. Ограничения/проблемы/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.

Ответ 11

Теперь вы можете делать Mixins с Java (т.е. 5,6,7) с помощью AspectJ ITDs. Java 8, конечно, добавит лучшие возможности с помощью своих методов защиты.

Ответ 13

Да, самый простой и удобный способ внедрения mixins apporoach в Java - использовать статический импорт из некоторого класса, который содержит статические методы.

Ответ 14

Не уверен, какие именно функции вы используете для миксинов, но многое из этого можно сделать, используя шаблон декоратора.

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

Ответ 15

Я изучаю это для Java 7. Мой первый разрез будет состоять в том, чтобы использовать пример, показанный в этой статье:

Он должен работать с java 6, он аналогичен другим вариантам инъекций выше. Основываясь на моем опыте с Mixins в С# и Ruby, вы должны стремиться к внедрению mixins, а не просто подражать или подделывать его.

Другая модель, используемая с Jackson:

Если вы можете использовать новую версию Java 8, скажем, если вы находитесь в режиме предварительного выпуска, это может помочь.

Использование метода Virtual Extension, который требует усилий для 'be-a' mixin. Поэтому, на мой взгляд, все еще рано, и я предпочитаю подход с более чистым взглядом (или похожий), предлагаемый первой ссылкой.

Ответ 16

Является ли термин "Mixin" не эквивалентен термину "термин" Java в аспектно-ориентированном программировании? AspectJ, вероятно, стоит посмотреть.

Ответ 17

Ответ на старый вопрос.

Я взглянул на 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!"

Ответ 18

Пожалуйста, посмотрите мой небольшой демонстрационный проект, как создавать микшины в чистом java с помощью cglib. В основном это просто вызов генератора прокси. Это союзник. Пример содержит тестовый пример junit, демонстрирующий, как создать прокси-сервер.

https://github.com/literadix/JavaMixins