Gostaria de saber se existe uma razão especial em Java para usar sempre " extends
" em vez de " implements
" para definir limites de parâmetros de tipo.
Exemplo:
public interface C {}
public class A<B implements C>{}
é proibido, mas
public class A<B extends C>{}
está correto. Qual o motivo disso?
java
generics
syntax
design-choices
user120623
fonte
fonte
implements
?" - "Porque só existeextends
".implements
que não traria nada de novo e complicaria ainda mais as coisas. Espero que seja útil para você.Respostas:
Não há diferença semântica na linguagem de restrição genérica entre se uma classe 'implementa' ou 'estende'. As possibilidades de restrição são 'extends' e 'super' - ou seja, é essa classe para operar com atribuível a essa outra (extends), ou é essa classe atribuível a essa (super).
fonte
class Generic<RenderableT extends Renderable implements Draggable, Droppable, ...> { Generic(RenderableT toDrag) { x = (Draggable)toDrag; } }
queira compilar verificações de tempo.A resposta está aqui :
Então, aí está, é um pouco confuso, e a Oracle sabe disso.
fonte
getFoo(List<? super Foo> fooList)
SOMENTE funciona com a classe que literalmente é estendida por Foo likeclass Foo extends WildcardClass
. Nesse caso, aList<WildcardClass>
seria uma entrada aceitável. No entanto, qualquer classe queFoo
implementa não funcionariaclass Foo implements NonWorkingWildcardClass
não significaList<NonWorkingWildcardClass>
que será válida nogetFoo(List<? super Foo> fooList)
. Claro como cristal!Provavelmente porque para ambos os lados (B e C) apenas o tipo é relevante, não a implementação. No seu exemplo
B também pode ser uma interface. "extends" é usado para definir subinterfaces e subclasses.
Geralmente penso em 'Sub estende Super' como ' Sub é como Super , mas com recursos adicionais', e 'Clz implementa Intf' como ' Clz é uma realização de Intf '. No seu exemplo, isso corresponderia: B é como C , mas com recursos adicionais. Os recursos são relevantes aqui, não a realização.
fonte
Pode ser que o tipo base seja um parâmetro genérico, portanto o tipo real pode ser uma interface de uma classe. Considerar:
Também na perspectiva do código do cliente, as interfaces são quase indistinguíveis das classes, enquanto que para o subtipo é importante.
fonte
Aqui está um exemplo mais envolvido de onde estender é permitido e, possivelmente, o que você deseja:
public class A<T1 extends Comparable<T1>>
fonte
É meio arbitrário qual dos termos usar. Poderia ter sido de qualquer maneira. Talvez os projetistas da linguagem pensassem em "estender" como o termo mais fundamental e "implementarem" como o caso especial de interfaces.
Mas acho
implements
que faria um pouco mais de sentido. Eu acho que isso comunica mais que os tipos de parâmetro não precisam estar em um relacionamento de herança, eles podem estar em qualquer tipo de relacionamento de subtipo.O Java Glossary expressa uma visão semelhante .
fonte
Estamos acostumados
e qualquer pequeno desvio dessas regras nos confunde muito.
A sintaxe de um tipo ligado é definida como
( JLS 12> 4.4. Variáveis de tipo>
TypeBound
)Se mudássemos, certamente adicionaríamos o
implements
casoe termine com duas cláusulas processadas de forma idêntica
( JLS 12> 4.3. Tipos e valores de referência>
ClassOrInterfaceType
)exceto que também precisaríamos cuidar
implements
, o que complicaria ainda mais as coisas.Eu acredito que é a principal razão pela qual
extends ClassOrInterfaceType
é usado em vez deextends ClassType
eimplements InterfaceType
- para manter as coisas simples dentro do conceito complicado. O problema é que não temos a palavra certa para cobrir tantoextends
eimplements
e nós definitivamente não queremos introduzir um.<T is ClassTypeA>
<T is InterfaceTypeA>
Embora
extends
traga alguma confusão quando acompanha uma interface, é um termo mais amplo e pode ser usado para descrever os dois casos. Tente ajustar sua mente ao conceito de estender um tipo (nãoestender uma classe, nãoimplementar uma interface). Você restringe um parâmetro de tipo por outro tipo e não importa qual seja esse tipo. Só importa que seja seu limite superior e seu supertipo .fonte
De fato, ao usar genérico na interface, a palavra-chave também é estendida . Aqui está o exemplo de código:
Existem 2 classes que implementam a interface Greeting:
E o código de teste:
fonte