Интересно, есть ли в Java особая причина использовать всегда " extends
", а не " implements
" для определения границ параметров типа.
Пример:
public interface C {}
public class A<B implements C>{}
запрещено, но
public class A<B extends C>{}
правильно. В чем причина этого?
java
generics
syntax
design-choices
user120623
источник
источник
implements
?" - «Потому что есть толькоextends
».implements
бы не принести ничего нового и еще больше усложнить ситуацию. Я надеюсь, что это будет полезно для вас.Ответы:
В родовом языке ограничений нет семантической разницы между «реализацией» или «расширением» класса. Возможны следующие ограничения: «расширяет» и «супер» - то есть, может ли этот класс работать с присваиваемым этому другому (расширяется) или этот класс назначается из этого (супер).
источник
class Generic<RenderableT extends Renderable implements Draggable, Droppable, ...> { Generic(RenderableT toDrag) { x = (Draggable)toDrag; } }
то хотел проверять время компиляции.Ответ здесь :
Итак, у вас это есть, это немного сбивает с толку, и Oracle это знает.
источник
getFoo(List<? super Foo> fooList)
ТОЛЬКО работает с классом, который буквально расширяется как Fooclass Foo extends WildcardClass
. В этом случаеList<WildcardClass>
будет приемлемым вход. Однако любой класс, которыйFoo
реализует не будет работатьclass Foo implements NonWorkingWildcardClass
, не означает,List<NonWorkingWildcardClass>
что будет действительным вgetFoo(List<? super Foo> fooList)
. Кристально чистый!Вероятно, потому что для обеих сторон (B и C) важен только тип, а не реализация. В вашем примере
B также может быть интерфейсом. «extends» используется для определения подинтерфейсов, а также подклассов.
Я обычно думаю о «Sub extends Super» как « Sub похож на Super , но с дополнительными возможностями», а «Clz реализует Intf», так как « Clz - реализация Intf ». В вашем примере это будет соответствовать: B похож на C , но с дополнительными возможностями. Здесь важны возможности, а не реализация.
источник
Может случиться так, что базовый тип является универсальным параметром, поэтому фактический тип может быть интерфейсом класса. Рассматривать:
Также с точки зрения клиентского кода интерфейсы практически неотличимы от классов, тогда как для подтипа это важно.
источник
Вот более сложный пример того, где можно использовать extends и, возможно, что вы хотите:
public class A<T1 extends Comparable<T1>>
источник
Это своего рода произвольно, какой из терминов использовать. Это могло быть так или иначе. Возможно, разработчики языка думали, что «расширяет» как самый фундаментальный термин, и «внедряет» как особый случай для интерфейсов.
Но я думаю, что
implements
было бы немного больше смысла. Я думаю, это больше говорит о том, что типы параметров не должны быть в отношениях наследования, они могут быть в любом виде отношений подтипа.Глоссарий Java выражает аналогичную точку зрения .
источник
Мы привыкли к
и любое небольшое отклонение от этих правил очень смущает нас.
Синтаксис привязки типа определяется как
( JLS 12> 4.4. Типовые переменные>
TypeBound
)Если бы мы изменили это, мы обязательно добавили бы
implements
случайи в конечном итоге с двумя одинаково обработанными предложениями
( JLS 12> 4.3. Типы ссылок и значения>
ClassOrInterfaceType
)кроме нас также нужно было бы позаботиться о том
implements
, что еще больше усложнит ситуацию.Я полагаю, что это главная причина, почему
extends ClassOrInterfaceType
используется вместоextends ClassType
иimplements InterfaceType
- чтобы все было просто в рамках сложной концепции. Проблема в том , что мы не имеем право слова , чтобы охватить какextends
иimplements
мы определенно не хотим , чтобы ввести одну.<T is ClassTypeA>
<T is InterfaceTypeA>
Хотя это
extends
вносит некоторую путаницу, когда речь идет о интерфейсе, это более широкий термин, и его можно использовать для описания обоих случаев. Попробуйте настроить свой разум на идею расширения типа (нерасширения класса, нереализации интерфейса). Вы ограничиваете параметр типа другим типом, и не имеет значения, что это за тип на самом деле. Имеет значение только то, что это его верхняя граница и его супертип .источник
Фактически, при использовании универсального интерфейса, ключевое слово также расширяется . Вот пример кода:
Есть 2 класса, которые реализуют интерфейс приветствия:
И тестовый код:
источник