ОО - проблема наследования или декорирования - PullRequest
4 голосов
/ 26 мая 2010

У меня есть вопрос, связанный с ООП. У меня есть интерфейс, скажем:

class MyInterface {
    public int getValue();
}

В моем проекте этот интерфейс реализован в 7 реализациях:

class MyImplementation1 implements MyInterface { ... }
...
class MyImplementation7 implements MyInterface { ... }

Эти реализации используются несколькими различными модулями. Для некоторых модулей поведение MyInterface должно быть немного изменено. Предположим, что он должен возвращать значение разработчика + 1 (для примера). Я решил это, создав маленький декоратор:

class MyDifferentInterface implements MyInterface {
   private MyInterface i;

   public MyDifferentInterface(MyInterface i) {
       this.i = i;
   }

   public int getValue() {
       return i.getValue() + 1;
   }
}

Это делает работу.

Вот моя проблема: один из модулей не принимает параметр MyInterface, но напрямую MyImplementation4. Причиной этого является то, что этому модулю необходимо определенное поведение MyImplementation4, которое не покрыто самим интерфейсом MyInterface. Но, и здесь возникает трудность, этот модуль также должен работать на модифицированной версии MyImplementation4. То есть getValue () должна возвращать +1;

Каков наилучший способ решить эту проблему? Я не могу найти решение, которое не включает много дубликатов кода.

Обратите внимание, что, хотя приведенный выше пример довольно маленький и простой, интерфейс и декоратор довольно большие и сложные.

Большое спасибо всем.

Ответы [ 4 ]

2 голосов
/ 26 мая 2010

Если это на Java, вы можете сделать

class ModifiedMyImplementation4 extends MyImplementation4
{
    @Override
    public int getValue()
    {
        return super.getValue() + 1;
    }
}

Нет дублирования кода!

0 голосов
/ 26 мая 2010

Это решение означает, что я должен скопируйте весь этот код

Не можете ли вы поместить код, который будет дублироваться, в абстрактный класс MyAbstractImplementation? Тогда два дочерних класса могут наследовать от абстрактного класса. Все, что ему нужно, - это один абстрактный метод, который даже не должен ничего делать, его просто нужно реализовать детям.

void foo(void);

Ребенок, которому нужно другое поведение, переопределяет метод. Потребитель должен будет принять тип MyAbstractImplementation вместо интерфейса. Вуаля, без дублирования кода.

0 голосов
/ 26 мая 2010

Вы можете попробовать что-то вроде:

public class MyDifferentImplementation4 extends MyImplementation4 {
    private MyDifferentInterface mdi;
    public MyDifferentImplementation4(MyDifferentInterface mdi) {
        this.mdi = mdi;
    }
    public getValue() {
        return mdi.getValue();
    }
}

Экземпляр MyDifferentInterface, переданный в конструктор, должен обернуть экземпляр MyImplementation4 (вы можете принудительно реализовать это, используя подкласс MyDifferentInterface, конструктор которого взял экземпляр MyImplementation4, а не интерфейс).

0 голосов
/ 26 мая 2010

Объявите getValue с ключевым словом virtual в MyImplementation4.

Унаследуйте новый класс от MyImplementation4 и используйте ключевое слово override, чтобы объявить функцию getValue и реализовать ее как return base.getValue()+1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...