2009-06-10 6 views
240

Интересно, есть ли в Java особая причина для использования всегда «extends», а не «implements» для определения границ типовых параметров.Java generics - почему разрешено «extends T», но не «реализует T»?

Пример:

public interface C {} 
public class A<B implements C>{} 

запрещено, но

public class A<B extends C>{} 

является правильным. В чем причина этого?

+44

Пожалуйста, отметьте ответ Tetsujin no Oni как правильный. – KomodoDave

+5

Я не знаю, почему люди думают, что ответ Тетсуджина нет Oni действительно отвечает на вопрос. Он в основном перефразирует наблюдения ОП, используя академическую формулировку, но не дает никаких аргументов. «Почему нет« инструментов »?» - «Потому что есть только« extends ». – ThomasR

+1

ThomasR: это потому, что речь идет не о «разрешенном», а о значении: нет никакой разницы в том, как вы пишете общий потребляющий тип с ограничением, связано ли ограничение с интерфейсом или типом предка. –

ответ

287

В обобщенном языке ограничений нет семантической разницы между тем, реализуется ли класс «реализует» или «расширяет». Возможности ограничения - «extends» и «super» - то есть, этот класс должен работать с назначаемым другому (extends), или этот класс можно назначить из этого (супер).

+0

@KomodoDave (я думаю, что рядом с ответом это замечательно, я не уверен, есть ли другой способ его пометить, иногда другие ответы могут содержать дополнительную информацию - например, у меня была конкретная проблема, которую я не мог решить и google отправляет вас сюда при поиске.) @Tetsujin no Oni (Можно ли использовать какой-то код для уточнения? thanx :)) – ntg

+0

@ntg, это очень хороший пример на вопросе, который ищет примеры - I 'll ссылку его в комментарии, а не встраивание в ответ на данный момент. http://stackoverflow.com/a/6828257/93922 –

+1

Я думаю, что причина в том, что, по крайней мере, я хотел бы иметь общий тип, который может иметь конструктор и методы, которые могут принимать любой класс, который и расширяет базовый класс, и демонстрирует интерфейс а не только интерфейсы, расширяющие интерфейс. Затем создайте экземпляр Genric-теста для присутствия интерфейсов и укажите фактический класс, заданный как параметр типа. В идеале я хотел бы класса 'Generic { Generic (RenderableT toDrag) { х = (Draggable) toDrag; } } ' Требуется выполнить проверку времени компиляции. – peterk

6

Возможно, базовый тип является общим параметром, поэтому фактический тип может быть интерфейсом класса. Рассмотрим:

class MyGen<T, U extends T> { 

Также от клиента код перспективные интерфейсы практически неотличимы от классов, в то время как для подтипа важно.

14

Возможно, потому что для обеих сторон (B и C) используется только тип, а не реализация. В вашем примере

public class A<B extends C>{} 

B может быть интерфейс, а также. «extends» используется для определения суб-интерфейсов, а также подклассов.

interface IntfSub extends IntfSuper {} 
class ClzSub extends ClzSuper {} 

Я обычно думаю о 'Sub распространяется Супер' как 'Sub, как Супер, но с дополнительными возможностями' и 'CLZ реализует Intf' как 'CLZ является реализация Intf '. В вашем примере это будет соответствовать: B - это как C, но с дополнительными возможностями. Здесь важны возможности, а не реализация.

+8

Рассмотрите . E не должен быть классом. –

7

Вот более сложный пример того, где проходит разрешено и, возможно, что вы хотите:

public class A<T1 extends Comparable<T1>>

2

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

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

Глоссарий Java выражает similar view.

-2

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

24

Ответ в here:

Чтобы объявить ограниченный тип параметра, список имя параметра типа, за которым следует extends ключевое слово, а затем его верхняя граница [...]. Обратите внимание, что в этом контексте расширения в общем смысле означают либо extends (как в классах), либо implements (как в интерфейсах).

Итак, у вас есть это, это немного запутанно, и Oracle это знает.