Почему Java запрещает наследование внутренних интерфейсов? - PullRequest
19 голосов
/ 03 ноября 2011

Т.е. почему следующая "циклическая зависимость" невозможна?

public class Something implements Behavior {
    public interface Behavior {
        // ...
    }
}

Поскольку интерфейсы не ссылаются на внешний класс, это должно быть разрешено;однако компилятор заставляет меня определять эти интерфейсы вне класса.Есть ли логическое объяснение этому поведению?

Ответы [ 3 ]

11 голосов
/ 03 ноября 2011

Соответствующие правила в спецификации:

http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.4

Класс C напрямую зависит от типа T, если T упоминается в предложении extends или реализаций C либо как суперкласс или суперинтерфейс, либо как спецификатор имени суперкласса или суперинтерфейса.

http://java.sun.com/docs/books/jls/third_edition/html/interfaces.html#9.1.3

Интерфейс I напрямую зависит от типа T, если T упоминается в предложении extends I как суперинтерфейс или как спецификатор в имени суперинтерфейса.

Следовательно, если A extends|implements B.C, A зависит от C и B. Затем Spec запрещает циклические зависимости.

Мотивация включения B в зависимость неясна. Как вы упомянули, если B.C повышен до верхнего уровня C2, то, что касается системы типов, мало что отличается, так почему A extends C2 в порядке, но не A extends B.C? Разумеется, вложенный тип B.C имеет некоторый привилегированный доступ к содержимому B, но я не могу найти в спецификации ничего, что могло бы сделать A extends B.C проблемным.

Единственная проблема, когда C является внутренним классом. Предположим, что B=A, A extends A.C следует запретить, поскольку существует циклическая зависимость «включающий экземпляр». Вероятно, это и есть реальная мотивация - запретить внешнему классу наследовать внутренний класс. Фактические правила более обобщенные, потому что они проще и в любом случае имеют смысл даже для не внутренних классов.

10 голосов
/ 03 ноября 2011

Представьте, что вы - компилятор.

Мы говорим, что вы создаете класс Something.Этот класс реализует Поведение ... Но Поведение еще не существует, потому что что-то еще не зарегистрировано *

Вы понимаете проблему?

Видите класс как блок, содержащий вещи.Поведение содержится в коробке Нечто.Но Нечто не существует.

0 голосов
/ 03 ноября 2011

Простого факта, что языковые спецификации запрещают это, должно быть достаточно.

Некоторые причины, которые я мог бы придумать:

  • Это было бы бесполезно.

  • По любым причинам, которые вы можете использовать, я уверен, что существуют лучшие варианты.

  • Дочерние классы должны расширять базовые классы, так почемуВы бы объявили базовый класс внутри его собственного потомка?

  • Было бы нелогично, если бы отдельный класс расширял ваш внутренний класс.

...