Из Effective Java Item 18, где он предлагает, мы можем объединить интерфейсы и абстрактные классы, предоставив абстрактный класс реализации скелета. Мне интересно, когда следует использовать скелетную реализацию для имитированного множественного наследования? и каковы преимущества и недостатки? Может ли кто-нибудь привести пример?
Почему и когда использовать реализацию скелета в java
Ответ 1
Точка "Скелетного класса", как вы выразились, заключается в основном в соблюдении определенных основных правил, которые будут определять использование вашего дизайна. Сами по себе интерфейсы и абстрактные классы не могут выполнять эту работу. Рассмотрим интерфейс, например
- Вы не можете указать какие-либо сведения о реализации своих методов
- переменные, указанные на уровне интерфейса, должны быть статическими.
- Интерфейсы ничего не могут реализовать (класс или интерфейс)
Таким образом, это означает, что использование только одного интерфейса для определения правил дизайна будет по-прежнему допускать злоупотребление операциями, определенными в вашем интерфейсе, вы не сможете указывать важные переменные уровня класса или в полной мере использовать наследование.
Теперь возьмем абстрактный класс
- Java не поддерживает множественное наследование, поэтому получение преимуществ нескольких классов, абстрактное или иное невозможно
- Вы не можете полностью извлечь выгоду из полиморфизма из абстрактного класса, основанного только на том, что интерфейсы (для меня) находятся на вершине дерева полиморфизма
Сочетание обоих дает вам лучшее из обоих миров в этом
- Абстрактный класс может реализовать интерфейс. Класс реализации может расширить ваш абстрактный класс, чтобы получить преимущества уже реализованных методов интерфейса. И эта цепочка может продолжаться столько абстрактных классов, сколько необходимо, вплоть до конкретной реализации
- Класс реализации может реализовать столько интерфейсов, сколько необходимо для целей маркерного типа. Таким образом, вы можете иметь столько интерфейсов
Serializable
для маркировки, которые будут расширены другими интерфейсами - Класс, реализующий абстрактный класс (который реализует интерфейс), может быть определен как тип интерфейса, чтобы извлечь выгоду из лучшего полиморфизма при создании в виде дочернего элемента абстрактного класса
Рассмотрим этот вариант использования
- У вас есть интерфейс, который имеет около 6 методов, которые будут определять использование класса, тогда у вас есть интерфейс маркера, который вам нужен просто для целей идентификации, поэтому вы можете использовать, возможно, оператор instanceOf.
- Теперь в этом первом интерфейсе вам необходимо выполнить определенную реализацию только из трех этих методов, а остальные 3 - для конечных пользователей этого класса.
- Таким образом, интерфейс A имеет 6 определений методов, интерфейс B - это всего лишь маркер для класса, который говорит: "Я - класс типа B". Теперь у вас будет класс A, абстрактный класс, реализующий оба интерфейса A и B
- В вашем абстрактном классе вы реализуете только нужные 3 метода. Затем вы оставляете детали реализации других 3 методов конечным потребителям этого абстрактного класса