Quem estende as interfaces? E porque?

20

AFAIK, minha classe extendspai classes e implementsinterfaces. Mas me deparo com uma situação em que não posso usar implements SomeInterface. É a declaração de um tipo genérico. Por exemplo:

public interface CallsForGrow {...}

public class GrowingArrayList <T implements CallsForGrow>  // BAD, won't work!
                              extends ArrayList<T> 

Aqui, o uso implementsé sintaticamente proibido. Pensei primeiro que o uso da interface dentro de <> é proibido, mas não. É possível, eu só tenho que usar em extendsvez de implements. Como resultado, estou "estendendo" uma interface. Este outro exemplo funciona:

public interface CallsForGrow {...}

public class GrowingArrayList <T extends CallsForGrow>  // this works!
                              extends ArrayList<T> 

Para mim, parece uma inconsistência sintática. Mas talvez eu não entenda alguns detalhes do Java 6? Existem outros lugares onde eu devo estender interfaces? A interface, que pretendo estender, deve ter alguns recursos especiais?

Gangnus
fonte

Respostas:

25

No caso de variáveis ​​de tipo genérico, o compilador não se importa se Té uma classe, uma interface, uma enumeração ou uma anotação. Tudo o que importa é que é um tipo com um determinado conjunto de sub e supertipos.

E não há razão para complicar a sintaxe apenas porque em outro local (onde você realmente implementa uma interface) a distinção entre classes e interfaces é relevante (por exemplo, se você é implementuma interface, precisa implementar todos os métodos que ela define, mas você não é necessário, se você é extenduma classe (não abstrata).

Supondo por um momento que você precise escrever implementsaqui, também precisará de uma sintaxe separada para enumvalores (em vez de simplesmente escrever <E extends Enum<E>>) e anotações (que você pode facilmente declarar usando <A extends Annotation>).

O único lugar em que você precisa escrever implementsé no ponto em que realmente implementa a interface. No que ponto (e nesse ponto apenas) a diferença é importante, porque você deve implementar os métodos definidos na interface. Para todos os outros, não importa se algum dado Aé uma classe base ou uma interface implementada B: é um supertipo e é isso que importa.

Observe também que há outro local onde você usa extendscom interfaces:

interface A {
}

interface B extends A {
}

Neste ponto, implementsestaria errado, porque B não implementa A .

Joachim Sauer
fonte
Se usarmos sua lógica, devemos usar 'extends SomeInterface' sempre , não apenas em genéricos.
Gangnus
2
@ Gangnus: não, porque para o implementador existe uma diferença concreta entre , extendse implementsé apenas quando se olha para o problema de uma perspectiva pura do sistema de tipos que não há diferença.
Joachim Sauer
1
Desculpe, eu não entendo o seu pensamento. --1. Por que devemos usar "uma perspectiva pura do sistema de tipos" em um caso e não no outro? --2. Por que as demandas sintáticas mudam nesses lugares diferentes? Você poderia explicar, por favor. Na resposta, se possível.
Gangnus
1
@ Gangnus: quem disse que Té uma aula? Tpoderia referenciar um tipo de interface ou um enumtipo.
Joachim Sauer
1
vindo de C #, toda essa discussão é ridícula. denotamos os supertipos de um tipo com :. e nos bastidores, uma interface é e sempre foi uma classe abstrata com a restrição de conter apenas abstractmembros virtual ( ) não implementados , de modo a permitir herança múltipla. literalmente não há diferença entre implementse extends. ambos poderiam ser substituídos pela mesma palavra ( extends) ou por algum símbolo arbitrário ( :) e nada seria perdido.
Sara
5

Quando o Java 5, e em particular os genéricos, foram disponibilizados inicialmente para desenvolvedores que haviam registrado um interesse, a sintaxe era bem diferente. Em vez de Set<? extends Foo>e Set<? super Bar>tinha Set<+Foo>e Set<-Foo>. No entanto, o feedback foi que não estava claro se +significava mais específico ou mais amplo (mais classes) . A Sun respondeu a esse feedback alterando a sintaxe, mas com a restrição de não introduzir novas palavras-chave, o que teria sido um problema de compatibilidade com versões anteriores.

O resultado é que nenhum dos dois é completamente natural. Como você observa, extendsestá sobrecarregado para falar de interfaces "estendendo" as classes, que não é a linguagem usada em outros contextos; e superé sobrecarregado para significar "é uma superclasse de", que é a direção oposta ao relacionamento anteriormente expresso pela palavra-chave, ou seja, referindo-se a uma superclasse.

No entanto, os fundamentos do que é uma interface não são afetados por essa alteração e não introduz interfaces especiais que são estendidas de uma nova maneira.

Peter Taylor
fonte
+1. Eu vejo e concordo. Mas Joachim Sauer descobriu meu pensamento errôneo de que T é necessariamente uma classe. Então, a resposta é dele. Sua compreensão é de um (ou 2) andar mais alto :-). Meu problema era mais primitivo. Obrigado mesmo assim pelo meu desenvolvimento.
Gangnus
2

Existem desvantagens em permitir e proibir essa sintaxe, e as de permitir são muito maiores.

Apenas pense nisso.

A separação de interface e implementação é um dos idiomas fundamentais de programação. Por isso, a sintaxe que permite soletrar "interface implementa alguma coisa" seria tão ruim quanto usar um sinal de adição para indicar a multiplicação de operandos.

mosquito
fonte
Está bem. Então, eu realmente não entendo alguma coisa. Eu considerei isso muito provável. Mas você ainda não explicou o problema, desculpe. T é uma representação de uma classe. Por que em um lugar eu uso T estende e em outro T implementa?
Gangnus
@ Gangnus no exemplo que você forneceu T refere-se ao parâmetro type que não é necessariamente uma classe - veja o que Joachim já lhe disse . Permitindo implementos para isso levaria à mesma confusão que eu mencionei
mosquito
Sim, eu já vi o comentário dele. Será marcado como a resposta quando colocada em resposta. Até que vocês dois tenham meus agradecimentos e +1.
Gangnus
-1

É preciso entender a programação orientada a interface como o próximo passo, enquanto a interface é compreendida. Diz o que é o uso real da interface. Qual o papel que ele desempenha em um programa Java (ou qualquer outra linguagem).

Deepak
fonte
2
Como sua resposta aborda as preocupações do OP? Por favor edite sua resposta para ser mais claro.