2008-11-04 5 views
14

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

ответ

12

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

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

+0

ok, так что нет никаких трюков, чтобы избежать необходимости делегирования и вызывать логический.method1, logic.method2, logic.method3 явно? это помогло бы сэкономить на печатании и шаблоне кода. – joshjdevl 2008-11-04 20:48:48

+1

@joshjdevl Есть, но это означает [взломать компилятор] (http://projectlombok.org/features/Delegate.html). – maaartinus 2012-06-30 14:42:44

3

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

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

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

17

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

4

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

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

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

+0

Поддерживает ли он черты или просто микшины? То есть когда есть конфликт b/w два метода с идентичными сигнатурами, побеждает ли один из них или обнаруживается как ошибка компилятора и дает вам какой-то способ разрешения конфликта? – 2011-03-07 21:59:25

+0

Решение метода @NeilTraft прогнозируемо и основано на заказах на публикацию, см. Http://qi4j.org/_core.html#core-api-mixin – eskatos 2012-09-06 12:42:05

3

QI4J позволяет использовать Примеси

0

Исполнительные простой подмешать/качество поддержки в Java с помощью CGLIB/javassit вполне легко. Вы можете посмотреть пример here для небольшого примера. Более полное, готовое к использованию решение может быть найдено: here

2

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

Это похоже на то, как Scala генерирует код виртуальной машины Java для признаков, как описано здесь How are Scala traits compiled into Java bytecode?

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

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); } 
} 

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

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

0

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