Обратная совместимая структура с новыми функциями

1

Мне нужно добавить новые функции в мою инфраструктуру, которая выглядит так:

interface firstInterface{}

abstract class ReadOnly extends Forward{}

class Reference extends ReadOnly implements firstInterface{}

Абстрактный класс ReadOnly - это ограничение возможностей Forward, бросая unsupportedaction. Теперь мне нужно поддерживать эту функцию, но в другом классе (таким образом, есть оба варианта).

Мой первый шаг был,

class baseReference implements firstInterface{}

abstract class ReadOnly extends Forward{}

class Reference extends baseReference, Readonly{}

class Loading extends baseReference, Forward{}

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

Теги:
oop
class-design

2 ответа

1

Благодарим композицию над наследованием. Оберните реализацию с другой реализацией через делегирование (шаблон адаптера)

public class ReadOnly implements Forward{

     private Forward delegate;

     public ReadOnly(Forward adaptee){
          //check for null here if you want
          this.delegate = adaptee;
     }

     public void loadFoo(Foo foo){
       //invalid since this is read-only
       //this is the exception mentioned in OP
       throw new UnsupportedAction():

     }


     public Foo readFoo(){
          //allowed return delegate foo
          return delegate.readFoo();
     }

}
  • 0
    Вперед это не интерфейс! Кроме того, как бы я реализовать Загрузка?
  • 0
    извините, ваш пример сбивает с толку, так как вы сказали, что class baseReference implements Forward{} . что подразумевает, что Форвард был интерфейсом. Чтобы ответить на ваш другой вопрос, загрузка реализована в базовом объекте. Версия только для чтения удаляет функцию загрузки, не позволяя вызывать методы загрузки делегатов.
Показать ещё 1 комментарий
0

Кажется, вы запутываете реализацию интерфейса с помощью реализации класса.

Позвольте мне ответить на ваш вопрос, используя текстовые диаграммы классов UML, вместо кода. Пожалуйста, считайте точки пустыми.

[1] Ваша инфраструктура имеет интерфейс под названием "FirstInterface", и этот интерфейс определяет метод "Load", возможно, существуют другие методы или свойства.

.....................................
..+-------------------------------+..
..|.........<<interface>>.........|..
..|........FirstInterface.........|..
..+-------------------------------+..
..|.[+].void Load()...............|..
..+-------------------------------+..
.....................................

Обратите внимание, что "+" внутри квадратных скобок означает, что функция или свойство могут быть доступны как "общедоступные".

[2] В вашей инфраструктуре есть класс под названием "ForwardClass", который поддерживает "FirstInterface".

Таким образом, этот класс имеет свой собственный метод "Загрузить".

.....................................
..+-------------------------------+..
..|.........<<interface>>.........|..
..|........FirstInterface.........|..
..+-------------------------------+..
..|.[+].void Load()...............|..
..+-------------------------------+..
..................|..................
................/---\................
................|.O.|................
..................|..................
..+-------------------------------+..
..|...........<<class>>...........|..
..|.........ForwardClass..........|..
..+-------------------------------+..
..|.[+].void Load()...<<virtual>>.|..
..+-------------------------------+..
.....................................

Обратите внимание, что в Java, в отличие от других языков, все методы считаются "виртуальными" и могут быть заменены без указания чего-либо.

Я буду использовать "виртуальный" текст, когда метод будет объявлен в первый раз, и "переопределить" текст на диаграммах, когда метод уже существует, и его заменить.

[3] Теперь класс "ForwardClass" расширяет его классом "ReadOnlyClass", который заменяет метод "Загрузить" и вызывает исключение, называемое "UnsupportedActionException", помните, что исключения - это особый вид классов или объектов.

Класс "ReadOnlyClass" также добавляет дополнительные методы.

.....................................
..+-------------------------------+..
..|...........<<class>>...........|..
..|.........ForwardClass..........|..
..+-------------------------------+..
..|.[+].void Load()...<<virtual>>.|..
..+-------------------------------+..
..................|..................
..................^..................
................./.\.................
................/---\................
..................|...........................................................
..+---------------------------------+......+-------------------------------+..
..|............<<class>>............|...+--|.........<<exception>>.........|..
..|..........ReadOnlyClass..........|...|..|...UnsupportedActionException..|..
..+---------------------------------+...|..+-------------------------------+..
..|.[+].void Load()....<<override>>.|---+.....................................
..|.[+].void DoExtra()..<<virtual>>.|.........................................
..+---------------------------------+.........................................
..............................................................................

[4] Теперь вы хотите расширить класс "ReadOnlyClass" с помощью "LoadingClass". Пусть suppouse добавляет некоторые свойства или заменяет метод DoExtra.

..............................................................................
..+---------------------------------+......+-------------------------------+..
..|............<<class>>............|...+--|.........<<exception>>.........|..
..|..........ReadOnlyClass..........|...|..|...UnsupportedActionException..|..
..+---------------------------------+...|..+-------------------------------+..
..|.[+].void Load()....<<override>>.|---+.....................................
..|.[+].void DoExtra()..<<virtual>>.|.........................................
..+---------------------------------+.........................................
..................|..................
..................^..................
................./.\.................
................/---\................
..................|..................
..+----------------------------------+..
..|............<<class>>.............|..
..|...........LoadingClass...........|..
..+----------------------------------+..
..|.[+].void DoExtra()..<<override>>.|..
..+----------------------------------+..
........................................

[5] Теперь давайте применим сценарий вашего сообщения.

Предположим, что вы хотите, чтобы любой объект "LoadingClass" также использовал метод "Загрузить" родительского класса "ForwardClass", игнорируя метод "Загрузить" родительского класса "ReadOnlyClass", который генерирует исключение.

Потенциальное решение, чтобы создать новый защищенный метод, называемый "ConfirmedLoad", в "ForwardClass". Давайте добавим поле с символом "#", чтобы очистить его "защищенный" метод.

Переместите весь код "Загрузить" в "ConfirmedLoad", а затем сделайте "Загрузить" выполнить "ConfirmedLoad".

Наследование классов продолжается так же, и другой код, который использует эти классы, не изменяется, с изменениями. Обратите внимание, что я не поместил "виртуальный" текст в "ConfirmedLoad", потому что мы не заинтересованы в замене этого метода.

............................................
..+---------------------------------------+..
..|...............<<class>>...............|..
..|.............ForwardClass..............|..
..+---------------------------------------+..
..|.[#].void ConfirmedLoad()..............|..
..|.[+].void Load()...........<<virtual>>.|..
..+---------------------------------------+..
.............................................

[6] Затем мы можем добавить логический метод "CanLoad" в "ReadOnlyClass", который в этом случае всегда возвращает false, но, ожидается, будет изменен позже. Мы также изменяем здесь метод "Загрузить", который вызывает функцию "CanLoad", а если asnwer - false, генерирует исключение.

............................................
..+---------------------------------------+..
..|...............<<class>>...............|..
..|.............ForwardClass..............|..
..+---------------------------------------+..
..|.[#].void ConfirmedLoad()..............|..
..|.[+].void Load()...........<<virtual>>.|..
..+---------------------------------------+..
..................|..................
..................^..................
................./.\.................
................/---\................
..................|..................
..+---------------------------------------+..
..|...............<<class>>...............|........+-------------------------------+..
..|.............ReadOnlyClass.............|.....+--|.........<<exception>>.........|..
..+---------------------------------------+.....|..|...UnsupportedActionException..|..
..|.[+].bool CanLoad()........<<virtual>>.|.....|..+-------------------------------+..
..|.[+].void Load()..........<<override>>.|..---+.....................................
..|.[+].void DoExtra()........<<virtual>>.|..
..+---------------------------------------+..
.............................................

[7] Теперь, в другом, чтобы сделать метод "Загрузить" в любом объекте "LoadingClass", затем замените метод "CanLoad", всегда возвращающий true.

.............................................
..+---------------------------------------+..
..|...............<<class>>...............|..
..|.............ForwardClass..............|..
..+---------------------------------------+..
..|.[#].void ConfirmedLoad()..............|..
..|.[+].void Load()...........<<virtual>>.|..
..+---------------------------------------+..
.......................|..................
.......................^..................
....................../.\.................
...................../---\................
.......................|..................
..+---------------------------------------+..
..|...............<<class>>...............|........+-------------------------------+..
..|.............ReadOnlyClass.............|.....+--|.........<<exception>>.........|..
..+---------------------------------------+.....|..|...UnsupportedActionException..|..
..|.[+].bool CanLoad()........<<virtual>>.|.....|..+-------------------------------+..
..|.[+].void Load()..........<<override>>.|..---+.....................................
..|.[+].void DoExtra()........<<virtual>>.|..
..+---------------------------------------+..
.......................|..................
.......................^..................
....................../.\.................
...................../---\................
.......................|..................
..+---------------------------------------+..
..|...............<<class>>...............|..
..|.............LoadingClass..............|..
..+---------------------------------------+..
..|.[+].bool CanLoad().......<<override>>.|..
..+---------------------------------------+..
.............................................

[8] Если вы добавляете другие классы, которые реализуют "LoadInterface", а также являются подклассами классов "ForwardClass", "ReadOnlyClass" или "LoadingClass", это не имеет значения, поскольку интерфейс может поддерживаться несколько раз, интерфейс добавляет только "Я ожидаю, что это", а не настоящий код.

.............................................
..+---------------------------------------+..
..|...............<<class>>...............|..
..|............FirstInterface.............|..
..+---------------------------------------+..
..|.[+].void Load().......................|..
..+---------------------------------------+..
.......................|......................
...................../---\....................
.....................|.O.|........................
.......................|..........................
.......................+-----------------------+..
.......................|.......................|..
.......................|.......................|..
..+---------------------------------------+....|..
..|...............<<class>>...............|....|..
..|.............ForwardClass..............|....|..
..+---------------------------------------+....|..
..|.[#].void ConfirmedLoad()..............|....|..
..|.[+].void Load()...........<<virtual>>.|....|..
..+---------------------------------------+....|..
.......................|.......................|..
.......................^.......................|..
....................../.\......................|..
...................../---\.....................|..
.......................|.......................|..
..+---------------------------------------+....|..
..|...............<<class>>...............|....|..
..|.............ReadOnlyClass.............|....|..
..+---------------------------------------+....|..
..|.[+].bool CanLoad()........<<virtual>>.|....|..
..|.[+].void Load()..........<<override>>.|....|..
..|.[+].void DoExtra()........<<virtual>>.|....|..
..+---------------------------------------+....|..
.......................|.......................|..
.......................^.......................|..
....................../.\......................|..
...................../---\.....................|..
.......................|.......................|..
..+---------------------------------------+....|..
..|...............<<class>>...............|....|..
..|.............LoadingClass..............|....|..
..+---------------------------------------+....|..
..|.[+].bool CanLoad().......<<override>>.|....|..
..+---------------------------------------+....|..
.......................|.......................|..
.......................^.......................|..
....................../.\......................|..
...................../---\.....................|..
.......................|.......................|..
..+---------------------------------------+....|..
..|...............<<class>>...............|----+..
..|...........BaseReferenceClass..........|.......
..+---------------------------------------+.......
..................................................

Класс "BaseReferenceClass" косвенно реализует интерфейс "FirstInterface" через класс "LoadingClass", но также снова реализует напрямую тот же интерфейс. Это его ОК с интерфейсами, но, НЕ с классами.

Если интерфейс "FirstInterface" был классом (может быть, абстрактным), проблема множественного дублированного наследования вызовет ошибку компиляции.

Приветствия.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню