Java черты или шаблон mixins?

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

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

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

Затем вы, сэр, ищете Apache Polygene (ранее Qi4J или Zest);)

Ответ 4

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

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

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

Ответ 5

QI4J позволяет использовать mixins

Ответ 6

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

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

Ответ 7

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

Ответ 8

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