Подтвердить что ты не робот

Как обернуть класс в java и сохранить интерфейс?

У меня есть класс вроде:

MyClass extends MyAbstractClass implement myInterface1, myInterface2,...

Мне нужно создать новый класс с дополнительными полями:

MyType1 field1;
MyType2 field2;
.......

Кажется, что правильно создать новый класс, который будет включать MyClass, например:

MyWrapClass {
 MyClass myClass=new MyClass(...);
 MyType1 field1;
 MyType2 field2;
 .....

Но MyWrapClass используется как тип myInterface1 или myInterface2!

Итак, вопрос: должен ли я объявлять все методы, необходимые для интерфейсов myInterface1, myInterface2 в MyWrapClass? Или существует другой способ? Спасибо.

4b9b3361

Ответ 1

В принципе, есть два способа. Первый заключается в расширении базового класса:

public class MySubClass extends MyClass {
     private MyType1 field1;
     private MyType2 field2;
....

Второй вариант заключается в использовании композиции:

public class MySubClass implements myInterface1, myInterface2 {
      private MyClass delegate;
      private MyType1 field1;
      private MyType2 field2;

      // for all methods in myInterface1, myInterface2
      public SomeType method1() {
         return delegate.method1();
      }
      ... 
}

Второй вариант рекомендуется многими Java-гуру:

Книга Джоша Блоха Эффективное Java 2nd Edition

  • Пункт 16: Офорт композиции над наследованием
  • Пункт 17: Проектирование и документ для наследования или запретить его

Хороший объектно-ориентированный дизайн - это не либеральное расширение существующих классов. Твой первый  инстинкт должен составлять вместо этого.

См. также http://en.wikipedia.org/wiki/Composition_over_inheritance

Состав над наследованием может упростить первоначальный дизайн классов Business Domain и обеспечить более стабильный бизнес-домен в долгосрочной перспективе. Его преимуществом перед наследованием является более тщательная изоляция интересов, чем может быть описана иерархией классов потомков. Кроме того, модели наследования часто придумываются при определении классов бизнес-домена, чтобы понять информацию в проблемной области и не обязательно отражать истинную взаимосвязь различных системных объектов.

P.S.: автогенерирующий код для композиции поддерживается некоторыми из современных IDE

Ответ 2

Не завершайте, просто подкласс:

class MySubClass extends MyClass {
    MyType1 field1;
    MyType2 field2;
    ...

Ответ 3

Предполагая, что вы не можете расширить MyClass, тогда нет другого способа, которым вы можете иметь MyWrapClass и использовать его, как MyClass. Например, мне удалось реализовать карту, чтобы обернуть фактическую карту. Он имеет много функций, и каждый из них должен быть реализован, который вы намереваетесь использовать. Здесь немного свободы, в том случае, если вы не планируете передавать ее функции, которую вы не пишете, вы можете добавить все необходимые методы и реализовать только те, которые вам нужны. Хотя чаще всего это не так.

В качестве альтернативы вы можете написать фиктивный класс, который реализует все методы интерфейсов, вызывающих оболочку. Затем вы можете переопределить этот класс своей собственной реализацией, позволяя вам перерабатывать класс-оболочку без необходимости выполнять все методы каждый раз.

Ответ 5

Предположим, вы не можете расширить MyClass и хотите использовать MyWrapClass как тип myInterface1 или myInterface2. Вы можете сделать следующее:

MyWrapClass implement myInterface1, myInterface2,...{
   MyClass myClass=new MyClass(...);
   MyType1 field1;
   MyType2 field2;

   methodInInterface1 () {
      myClass.methodInInterface1 ()
   }

   ....

Вы делегируете реализацию всех методов в myInterface1 и myInterface2 в MyClass. Я считаю, что это называется композицией.