Должен интерфейс, который наследован от базового класса быть реализованным явно в подклассе?

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

Например, если Вы хотите записать класс, который выполняет контракт интерфейса java.util.List. Вы реализуете это, расширяя класс java.util.AbstractList, это уже реализует интерфейс List. Вы явно объявляете, что Вы реализуете Список?

public class MyList extends AbstractList implements List

Или Вы сохраняете ввод при помощи неявного пути?

public class MyList extends AbstractList

Какой путь считают лучшим стилем? Какие причины необходимо предпочесть так или иначе? В которых ситуациях Вы предпочли бы путь 1 или путь 2?

13
задан slayton 13 August 2012 в 02:10
поделиться

10 ответов

Я задал этот тот же вопрос давно на моем блоге. Существует долгое обсуждение там также, если Вы интересуетесь наблюдением мыслей некоторых других людей. Интересно отметить, что обе стратегии взяты в JDK.

Я в конечном счете решил, что твердое правило об этом не имело смысла - лучше использовать лучшее решение относительно того, что я хотел передать.

4
ответ дан 1 December 2019 в 20:44
поделиться

Избегайте дублирования. Используйте метод 2.

Используйте @Override для переопределений.

12
ответ дан 1 December 2019 в 20:44
поделиться

Это не вопрос "о стиле". При расширении AbstractList, который уже реализует Список, Вы не должны явно реализовывать Список.

Это не просто вопрос сохранения ввода. Поскольку дополнительный "Список реализаций" избыточен, кто-то мог бы провести некоторое время, пытаясь выяснить, почему это там. Вы по существу пишете в гарантии, это уже - часть языка.

7
ответ дан 1 December 2019 в 20:44
поделиться

Если Вы заботитесь о пользователе Вашей способности класса, получают список реализованных интерфейсов через Class.getInterfaces () затем, Ваш класс должен упомянуть все интерфейсы в списке реализаций it. Class.getInterfaces () не возвратит интерфейсы, реализованные суперклассами. Следующая программа распечатает 1 и затем 0.

import java.io.Serializable;

class Test implements Serializable {
    class Inner extends Test {
    }

    public static void main(String[] argv) throws Exception {
        System.out.println(Test.class.getInterfaces().length);
        System.out.println(Inner.class.getInterfaces().length);
    }
}
2
ответ дан 1 December 2019 в 20:44
поделиться

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

Примечание Стороны: в Java существует столько классов и кто знает их всех? Еще больше, кто знает, от каких классов каждый класс реализует? Вы вводящий для дополнительной пары секунды сохраняете такого же разработчика минута или два смотрящих класса.

1
ответ дан 1 December 2019 в 20:44
поделиться

Другие комментаторы говорят, что необходимо избежать дублирования, и я соглашаюсь с ними.

Для ответа на общий вопрос единственный случай, я могу думать для утверждения и был бы, если Вы расширили (скажем), AbstractFrotzer и реализовали Frobner, AbstractFrotzer реализовал Frobner, но у Вас была причина полагать, что это не могло бы в будущем. Если AbstractFrotzer действительно абстрактен, то он даже не мог бы реализовать все методы Frobner сам. Это означает, что для кого-то возможно изменить контракт для AbstractFrotzer без того, что вы имели необходимость изменить Ваш класс или любой другой код, который полагался на Ваш класс, чтобы быть Frobner. Я, однако, полагал бы, что это очень редкое обстоятельство, и даже если бы оно произошло, и Ваш класс только расширил AbstractFrotzer, то было бы достаточно легко дать ему быструю семантическую проверку и, при необходимости, добавить пункт реализаций к нему в той точке.

1
ответ дан 1 December 2019 в 20:44
поделиться

В то время как я обычно придерживаюсь опции 2, я буду идти на конечность и утверждать, что опция 1 является на самом деле соответствующей в большем количестве случаев, когда это, применяются.

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

В правильно написанном классе в типичном случае название класса должно сделать это очевидным, что это реализует интерфейс. Добавление интерфейса было бы просто redundnacy.

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

1
ответ дан 1 December 2019 в 20:44
поделиться

При расширении AbstractList MyList уже имеет Список 'типа', таким образом, нет никакой потребности к explicityly статистике (или реализация) интерфейса.

0
ответ дан 1 December 2019 в 20:44
поделиться

Как правило используйте опцию 2, не опцию 1.

Опция 1 не предоставляет дополнения значения разработчику или кому-то, кто собирается поддержать код в подавляющем большинстве случаев..

Если кто-то действительно хочет знать все корни конкретного класса, любой IDE должен смочь сделать это для Вас, простой. (Eclipse: ctrl+shift+G)

Что, если AbstractList решает не реализовать Список еще? Это не собирается происходить для подавляющего большинства общих классов. Что относительно другое менее очевидное (менее защищенный)? Конечно, могут быть исключения, но очень немногие (<1%?)

0
ответ дан 1 December 2019 в 20:44
поделиться

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

Что, если базовый класс реализует несколько интерфейсов? Вы затем явно реализуете все те интерфейсы и полностью создаете резервную копию цепочки наследования? Очевидно, не, таким образом, я думаю, несоответствие этого подхода оказывается для несправедливости. Намерение может быть передано во многих отношениях, и это не лучший подход, по моему скромному мнению.

0
ответ дан 1 December 2019 в 20:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: