Многокомпонентный композитинг Java и сокращение котельной плиты
Мы все знаем, почему Java не имеет / не должна иметь множественное наследование. Так что это не вопрос о том, что уже обсуждалось до возвращения коров домой.
Здесь обсуждается, что мы будем делать, когда мы хотим создать класс, имеющий характеристики двух или более других классов.
Вероятно, большинство из нас сделали бы это, чтобы "наследовать" от трех классов. Для простоты я не учел конструктор.
class Car
extends Vehicle
{
final public Transport transport;
final public Machine machine;
}
Таким образом, класс Car напрямую наследует методы и объекты класса Vehicle, но должен явно ссылаться на транспорт и машину, чтобы ссылаться на объекты, созданные в Transport и Machine.
Car car = new Car();
car.drive(); // from Vehicle
car.transport.isAmphibious(); // from Transport
car.machine.getCO2Footprint(); // from Machine
Я думал, что это хорошая идея до тех пор, пока я не столкнусь с фреймворками, которые требуют методов установки и получения. Например, XML
<Car amphibious='false' footPrint='1000' model='Fordstatic999'/>
будет искать методы setAmphibious(..), setFootPrint(..) и setModel(..). Поэтому я должен спроектировать методы из классов транспорта и машин
class Car
extends Vehicle
{
final public Transport transport;
final public Machine machine;
public void setAmphibious(boolean b){
this.transport.setAmphibious(b);
}
public void setFootPrint(String fp){
this.machine.setFootPrint(fp);
}
}
Это нормально, если бы было только несколько характеристик. Сейчас я пытаюсь адаптировать все SmartGWT в GWT UIBinder, особенно те классы, которые не являются виджетами GWT. Есть много характеристик для проекта.
Было бы неплохо, если бы существовала какая-то форма аннотации, подобная этой:
class Car
extends Vehicle
@projects {Transport @projects{Machine @projects Guzzler}}
{
/* No need to explicitly instantiate Transport, Machine or Guzzler */
....
}
Там, где существуют общие названия характеристик, характеристики машины будут иметь приоритет у Гуззлера, а у транспорта будет приоритет над машиной, а у транспортного средства будет приоритет над транспортом. Инфраструктура аннотаций затем создаст экземпляры Transport, Machine и Guzzler как скрытых членов Car и расширится, чтобы разбить защищенные / общедоступные характеристики в порядке приоритета, заданном последовательностью аннотаций @project, в фактический исходный код или в байт-код. Желательно в байт-код. Так что метод setFootPrint найден как в Machine, так и в Guzzler, будет проецироваться только метод Machine.
Вопросы:
- Не кажется ли вам хорошей идеей иметь такую основу?
- Такая структура уже существует? Скажи мне, где / что.
- Есть ли плагин Eclipse, который это делает?
- Есть ли где-нибудь предложение или план, который вы знаете о такой структуре аннотаций?
Также было бы замечательно, если бы структура аннотаций / плагинов позволяла мне указывать, что boolean, int или что-либо еще должно быть преобразовано из String и выполняет преобразование / синтаксический анализ для меня тоже.
Пожалуйста, посоветуйте кто-нибудь. Надеюсь, формулировка моего вопроса была достаточно ясной. Спасибо.
Отредактировано: чтобы избежать спешных выводов, я переименовал название этого вопроса.
3 ответа
Возможно, не совсем то, что вы ищете, но вы можете взглянуть на Mixins:
- статья в википедии
- Рамки Qi4j
- CGLIB миксин поддержка
- этот пример
Если у вас есть свобода в вашей среде, обязательно посмотрите на Scala. У него есть черты, которые позволят вам решить эту проблему чисто. Черты являются композиционными (pdf) и предлагают гораздо лучшую стратегию повторного использования кода, чем наследование.
Вернувшись на землю Java, вы можете использовать AspectJ Inter-Type объявления для достижения чего-то похожего (mixins). Для этого есть также очень хороший плагин Eclipse: AJDT.
Некоторые фреймворки (по крайней мере Spring) поддерживают указание пути для сеттеров и геттеров. Так что сеттер будет выглядеть как
<property name="transport.amphibious" value="true" />
Вы должны увидеть, можете ли вы использовать такие опции.