черты ява или миксинс? - PullRequest
       33

черты ява или миксинс?

15 голосов
/ 04 ноября 2008

Есть ли способ эмулировать миксины или черты в Java? в основном мне нужен способ сделать множественное наследование, чтобы я мог добавить общую бизнес-логику к нескольким классам

Ответы [ 8 ]

17 голосов
/ 04 ноября 2008

Не так, как вы хотите это сделать. Эффективная Java рекомендует, чтобы вы "предпочитали композицию наследованию". Это означает, что вы перемещаете общую логику в другие классы и делегируете. Вот как вы обходите отсутствие множественного наследования в Java.

12 голосов
/ 04 ноября 2008

Я бы инкапсулировал всю бизнес-логику в новый класс BusinessLogic, и каждый класс, которому нужно BusinessLogic, делал бы вызовы в класс. Если вам нужна единственная корневая иерархия для ваших классов, которые делают вызовы BusinessLogic, вам также нужно будет создать интерфейс (BusinessLogicInterface?)

В псевдокоде:

interface BusinessLogicInterace
{
    void method1();
    void method2();
}

class BusinessLogic implements BusinessLogicInterface
{
    void method1() { ... }
    void method2() { ... }
}

class User 
    extends OtherClass 
    implements BusinessLogicInterface
{
    BusinessLogic logic = new BusinessLogic();

    @Override
    void method1() { logic.method1(); }

    @Override
    void method2() { logic.method2(); }
}

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

4 голосов
/ 04 ноября 2008

Сегодня в вас шевелится объект-пурист?

Думаете, что вы могли бы сделать с небольшим композитно-ориентированным программированием?

Тогда вы, сэр, ищете Apache Polygene (ранее Qi4J или Zest);)

3 голосов
/ 14 октября 2010

QI4J позволяет использовать миксины

3 голосов
/ 04 ноября 2008

Ответом Java на множественное наследование является возможность реализации нескольких интерфейсов. Конечно, это означает, что вы получите объявления методов, но не логику.

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

При проектировании классов Java я не обнаружил отсутствие множественного наследования в стиле C ++, которое мешало бы проектированию моей архитектуры. Вы найдете способ достичь того, что вы хотите сделать.

2 голосов
/ 02 мая 2013

Вы можете использовать тот факт, что интерфейсы позволяют вложенным классам (автоматически общедоступным статическим) сохранять реализацию по умолчанию методов интерфейса, инкапсулированных в самом интерфейсе. То есть переместите класс BusinessLogic примера Алекса Б. в интерфейс.

Это похоже на способ, которым Scala генерирует код JVM для признаков, как описано здесь Как признаки Scala компилируются в байт-код Java?

При этом пример становится:

interface BusinessLogicInterface {
    void method0();

    class DefaultImpl {
        private DefaultImpl() {
        }

        public static void method1(BusinessLogicInterface self) { ... }
        public static void method2(BusinessLogicInterface self) { ... }
    }

    void method1();
    void method2();
}

class User extends OtherClass implements BusinessLogicInterface {
    @Override
    void method0() { ... }

    @Override
    void method1() { BusinessLogic.defaultImpl.method1(this); }

    @Override
    void method2() { BusinessLogic.defaultImpl.method2(this); }
}

Обратите внимание, что мы передаем объект типа интерфейса в качестве параметра "self". Это означает, что бизнес-логика может использовать другие абстрактные методы (method0). Это может быть очень полезно для создания черты с абстрактными методами, которые все ортогональны друг другу, и полезными методами «расширения», которые могут быть реализованы в терминах этих ортогональных методов.

Недостатком является то, что каждый интерфейс должен копировать / вставлять код делегирования шаблонов. Другой часто используемый шаблон в Java без этого недостатка (но с меньшей согласованностью и меньшим количеством ОО-способов вызова методов) - создание класса с множественным именем в качестве интерфейса, содержащего статические методы, это используется в служебном классе Collections.

0 голосов
/ 18 мая 2015

Начиная с Java-8, были добавлены методы интерфейса по умолчанию. Это, вместе с множественным наследованием интерфейсов в Java, должно позволить что-то вроде смешивания. Очевидно, что интерфейсы должны работать независимо друг от друга. Таким образом, будут существенные ограничения.

0 голосов
/ 21 октября 2011

Реализация простой поддержки mixin / traits в java с использованием CGLib / javassit довольно проста. Вы можете посмотреть, например, здесь для небольшого примера. Более полное, готовое к использованию решение может быть найдено: здесь

...