Вопрос

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

Это было полезно?

Решение

Я бы инкапсулировал всю бизнес-логику в новый класс 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(); }
}

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

Другие советы

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

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

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

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

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

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

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

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

Вы можете использовать тот факт, что интерфейсы позволяют вложенным классам (автоматически общедоступным статическим) сохранять реализацию по умолчанию методов интерфейса, инкапсулированных в самом интерфейсе. То есть переместите класс 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). Это может быть очень полезно для создания черты с абстрактными методами, которые все ортогональны друг другу, и полезность "extension" методы, которые могут быть реализованы в терминах этих ортогональных методов.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top