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

Я просматривал JMS API из J2EE и обнаружил странное поведение, когда определенные методы, объявленные в интерфейсе (например, createQueue в сеансе), снова объявляются в подинтерфейсах, таких как QueueSession, и с идентичной документацией.

Поскольку субинтерфейс «наследует» все объявления методов интерфейса, который он наследует, и поскольку инструмент JavaDoc без проблем сортирует JavaDocs субинтерфейса и создает список «унаследованных операций», я не могу понять, что это дает.

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

Итак, вопрос: есть ли убедительная причина для повторного объявления метода в субинтерфейсе?


person Uri    schedule 19.02.2009    source источник


Ответы (5)


Видя, как это иногда происходит во время работы в Sun, я могу рассказать вам, как это обычно происходит. Кто-то определяет интерфейс, скажем, Алису, с помощью некоторых методов; многие разработчики реализуют этот интерфейс.

Некоторое время спустя выяснилось, что им нужен какой-то другой интерфейс, назовем его Боб, который имеет подмножество методов Алисы, чтобы позволить ему служить базовым интерфейсом для другого интерфейса, Клары. .

Если вы переместите методы Алисы в Боба, вы сломаете весь код, реализующий Алису; вы должны вернуться и хотя бы перекомпилировать целую кучу кода, некоторые из которых могут вам не принадлежать и по политическим причинам не могут быть взломаны.

Так что нет.

person Charlie Martin    schedule 19.02.2009
comment
В этом есть смысл. Но почему бы не изменить JavaDocs в суперклассе и сказать что-то вроде «Сделай мне одолжение, никогда не вызывай меня напрямую, создай экземпляр субинтерфейса»? - person Uri; 19.02.2009
comment
Потому что это было бы признанием ошибки? А если серьезно, может случиться так, что интерфейс суперкласса иногда используется сам по себе; нет причин, по которым рефакторинг не может заключаться в простом удалении методов. - person Charlie Martin; 19.02.2009
comment
стало понятно, что им нужен какой-то другой интерфейс, назовем его Боб, который имеет подмножество методов Алисы. Если все, что им нужно, это подмножество Алисы, почему они не могут сделать Боба отдельным интерфейсом с несколькими методами Алисы, вместо того, чтобы сделать Алису своим суперклассом? - person Jagat; 10.03.2012
comment
Потому что иногда наследование важно. Теперь объект Bob может содержаться в массиве Алисы. Так вот, иногда вам это не нужно, и тогда вы не должны этого делать. Но если вам это нужно, вы должны это сделать. - person Charlie Martin; 10.03.2012
comment
@CharlieMartin - все еще была отличная компания со многими замечательными людьми, которые были чрезвычайно осведомлены, жаль, что она подошла к концу. - person JonH; 17.05.2012
comment
Если вы переместите методы Алисы в Боба, вы сломаете весь код, реализующий Алису Почему это так? поскольку вы удаляете, но также добавляете Alice extends Bob - person haelix; 04.02.2019
comment
@haelix В этом примере Боб расширяет Алису. Это ошибка времени компиляции, чтобы затем заставить Алису расширить Боба — класс Graph должен быть ациклическим. - person Charlie Martin; 04.02.2019
comment
@CharlieMartin, второй абзац ответа (Некоторое время спустя это осознается...) подсказывает мне, что некоторые методы Алисы должны перейти к Бобу и Кларе. Так получается, что Алиса и Клара расширяют возможности Боба. (PS только что понял, что вы ответили на этот вопрос 10 лет назад, уважаемый!!) - person haelix; 04.02.2019
comment
@haelix Дело в том, что Алиса не может расширить Боба, потому что Боб уже расширяет Алису. Теперь вы можете рефакторить весь этот стек, поместив Боба на вершину графика, а Алиса и Клара расширит возможности Боба, но тогда каждое приложение, использующее Алису, должно быть перекомпилировано или рефакторинг для соответствия. С чем-то вроде JMS, где потенциально миллионы клиентов использовали его, это вызывает большой ужас. Так что нет. И кстати спасибо. - person Charlie Martin; 05.02.2019

В Java 5 вы можете изменить возвращаемый тип переопределяющего метода, сделав его более конкретным. Чаще всего документация отличается, поэтому метод должен быть объявлен снова.

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

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

person Peter Lawrey    schedule 19.02.2009

Я никогда не видел веских аргументов для этого. Лучшее, что я видел, это то, что:

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

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

Никогда не недооценивайте лень разработчика :-)

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

person TofuBeer    schedule 19.02.2009

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

person Alex Miller    schedule 19.02.2009

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

person Ray Tayek    schedule 19.02.2009
comment
Это невозможно с интерфейсом. Видимость метода определяется видимостью самого интерфейса. И вам не разрешено уменьшать видимость в подинтерфейсе. - person Alex Miller; 19.02.2009
comment
Кроме того, Cloneable не имеет методов - person oxbow_lakes; 20.02.2009