Do meu entendimento, se você implementar uma interface em java, os métodos especificados nessa interface devem ser usados pelas subclasses que implementam a referida interface.
Percebi que em algumas interfaces, como a interface Collection, existem métodos comentados como opcionais, mas o que isso significa exatamente? Isso me surpreendeu um pouco, pois pensei que todos os métodos especificados na interface seriam necessários?
Respostas:
Parece haver uma grande confusão nas respostas aqui.
A linguagem Java requer que todos os métodos em uma interface sejam implementados por todas as implementações dessa interface. Período. Não há exceções a esta regra. Dizer "Coleções são uma exceção" sugere uma compreensão muito confusa do que realmente está acontecendo aqui.
É importante perceber que existem dois níveis de conformidade com uma interface:
O que a linguagem Java pode verificar. Isso basicamente se resume a: há alguma implementação para cada um dos métodos?
Cumprindo o contrato de fato. Ou seja, a implementação faz o que a documentação na interface diz que deveria?
Interfaces bem escritas incluirão documentação explicando exatamente o que se espera das implementações. Seu compilador não pode verificar isso para você. Você precisa ler os documentos e fazer o que eles dizem. Se você não fizer o que o contrato diz, você terá uma implementação da interface no que diz respeito ao compilador , mas será uma implementação defeituosa / inválida.
Ao projetar a API de coleções, Joshua Bloch decidiu que, em vez de ter interfaces muito refinadas para distinguir entre diferentes variantes de coleções (por exemplo: legível, gravável, acesso aleatório, etc.), ele teria apenas um conjunto muito grosso de interfaces, principalmente
Collection
,List
,Set
eMap
, em seguida, documentar certas operações como "opcional". Isso era para evitar a explosão combinatória que resultaria de interfaces refinadas. Das Perguntas frequentes sobre o design da API de coleções Java :Quando os métodos na API de coleções são documentados como sendo "operações opcionais", isso não significa que você pode simplesmente deixar a implementação do método de fora na implementação, nem significa que você pode usar um corpo de método vazio (por um lado, muitos dos eles precisam retornar um resultado). Em vez disso, significa que uma escolha de implementação válida (aquela que ainda está em conformidade com o contrato) é lançar um
UnsupportedOperationException
.Observe que porque
UnsupportedOperationException
é um,RuntimeException
você pode lançá-lo a partir de qualquer implementação de método, no que diz respeito ao compilador. Por exemplo, você pode jogá-lo de uma implementação deCollection.size()
. No entanto, tal implementação violaria o contrato, pois a documentação paraCollection.size()
não diz que isso é permitido.À parte: a abordagem usada pela API de coleções do Java é um tanto controversa (provavelmente menos agora do que quando foi introduzida pela primeira vez, no entanto). Em um mundo perfeito, as interfaces não teriam operações opcionais e, em vez disso, seriam usadas interfaces refinadas. O problema é que o Java não suporta nem tipos estruturais inferidos ou tipos de interseção, e é por isso que tentar fazer as coisas da "maneira certa" acaba se tornando extremamente difícil no caso de coleções.
fonte
There are no exceptions to this rule
. Quer saber por que essa resposta não foi marcada como aceita. Outros são bons, mas você deu mais do que o suficiente.Foo
que não implementeRunnable
com método públicovoid run()
. Agora crie uma classeBar
queextends Foo
eimplements Runnable
sem exagerarrun
. Ele ainda implementa o método, embora indiretamente. Da mesma forma, uma implementação de método padrão ainda é uma implementação.remove
foi dada uma implementação padrão. Se você não implementá-lo, sua classe obterá a implementação padrão. Os outros dois métodos que você mencionou não têm implementações padrão.Para compilar uma classe de implementação (não abstrata) para uma interface - todos os métodos devem ser implementados.
No entanto , se pensarmos em um método em que sua implementação é uma simples exceção lançada como um 'não implementado' (como alguns métodos na
Collection
interface), então aCollection
interface é a exceção neste caso, não o caso regular. Normalmente , a classe de implementação deve (e irá) implementar todos os métodos.O "opcional" na coleção significa que a classe de implementação não precisa 'implementá-la' (de acordo com a terminologia acima), e ela apenas lançará
NotSupportedException
).Um bom exemplo -
add()
método para coleções imutáveis - o concreto irá apenas implementar um método que não faz nada além de lançarNotSupportedException
No caso de
Collection
ser feito para evitar árvores de herança confusas, isso deixará os programadores infelizes - mas para a maioria dos casos, esse paradigma não é recomendado e deve ser evitado se possível.Atualizar:
A partir do java 8, um método padrão foi introduzido.
Isso significa que uma interface pode definir um método - incluindo sua implementação.
Isso foi adicionado para permitir a adição de funcionalidade às interfaces, ao mesmo tempo em que oferece suporte à compatibilidade com versões anteriores para partes de código que não precisam da nova funcionalidade.
Observe que o método ainda é implementado por todas as classes que o declaram, mas usando a definição da interface.
fonte
Uma interface em Java apenas declara o contrato para implementação de classes. Todos os métodos nessa interface devem ser implementados, mas as classes de implementação são livres para deixá-los não implementados, viz., Em branco. Como um exemplo inventado,
Agora deixei
doSomethingElse()
sem implementação, deixando-o livre para implementação de minhas subclasses. Isso é opcional.No entanto, se você está falando sobre interfaces de coleção, como outros já disseram, elas são uma exceção. Se certos métodos não forem implementados e você os chamar, eles podem lançar
UnsupportedOperationException
exceções.fonte
Os métodos opcionais na interface Collection significam que a implementação do método pode lançar uma exceção, mas deve ser implementado de qualquer maneira. Conforme especificado nos documentos :
fonte
new Runnable ( ) { @ Override public void run ( ) { throw new UnsupportedOperationException ( ) ; } }
:;add((T)null)
pode ser válido em um caso, mas não em outro. Ou seja, fala sobre exceções / comportamento opcionais e para argumentos ("restrições de elementos" ... "exceções de elemento inelegível" ... "marcadas como opcionais") e não aborda métodos opcionais .Todos os métodos devem ser implementados para que o código seja compilado (exceto aqueles com
default
implementações em Java 8+), mas a implementação não precisa fazer nada funcionalmente útil. Especificamente, ele:UnsupportedOperationException
(ou similar)A última abordagem é freqüentemente usada nas classes de coleção - todos os métodos ainda são implementados, mas alguns podem lançar uma exceção se chamados em tempo de execução.
fonte
Na verdade, estou inspirado por SurfaceView.Callback2. Eu acho que esta é a forma oficial
Se sua classe não precisa implementar métodos opcionais, apenas "implementa Callback". Se sua classe precisa implementar métodos opcionais, apenas "implementa CallbackExtended".
Desculpe pelo inglês de merda.
fonte
No Java 8 e posterior, a resposta a esta pergunta ainda é válida, mas agora é mais matizada.
Primeiro, essas afirmações da resposta aceita permanecem corretas:
Então, qual é a nuance que há de novo no Java 8? Ao falar de "Métodos Opcionais", qualquer um dos seguintes agora é adequado:
1. Um método cuja implementação é contratualmente opcional
A "terceira declaração" diz que os métodos abstratos de interface devem sempre ser implementados e isso permanece verdadeiro no Java 8+. No entanto, como no Java Collections Framework, é possível descrever alguns métodos abstratos de interface como "opcionais" no contrato.
Nesse caso, o autor que está implementando a interface pode optar por não implementar o método. O compilador irá insistir em uma implementação, entretanto, e então o autor usa este código para quaisquer métodos opcionais que não são necessários na classe de implementação específica:
No Java 7 e anteriores, esse era realmente o único tipo de "método opcional" que existia, ou seja, um método que, se não implementado, gerava uma exceção UnsupportedOperationException. Esse comportamento é necessariamente especificado pelo contrato de interface (por exemplo, os métodos de interface opcionais do Java Collections Framework).
2. Um método padrão cuja reimplementação é opcional
Java 8 introduziu o conceito de métodos padrão . Esses são métodos cuja implementação pode ser e é fornecida pela própria definição de interface. Geralmente, só é possível fornecer métodos padrão quando o corpo do método pode ser escrito usando outros métodos de interface (ou seja, os "primitivos") e quando
this
pode significar "este objeto cuja classe implementou esta interface".Um método padrão deve cumprir o contrato da interface (assim como qualquer implementação de outro método de interface deve). Portanto, especificar uma implementação do método de interface em uma classe de implementação fica a critério do autor (desde que o comportamento seja adequado ao seu propósito).
Nesse novo ambiente, o Java Collections Framework pode ser reescrito como:
Dessa forma, o método "opcional"
add()
tem o comportamento padrão de lançar uma UnsupportedOperationException se a classe de implementação não fornecer um novo comportamento próprio, que é exatamente o que você gostaria que acontecesse e que é compatível com o contrato de List. Se um autor está escrevendo uma classe que não permite que novos elementos sejam adicionados a uma implementação de List, a implementação deadd()
é opcional porque o comportamento padrão é exatamente o que é necessário.Nesse caso, a "terceira instrução" acima ainda é válida, porque o método foi implementado na própria interface.
3. Um método que retorna um
Optional
resultadoO novo tipo final de método opcional é simplesmente um método que retorna um
Optional
. AOptional
classe oferece uma maneira decididamente mais orientada a objetos de lidar com osnull
resultados.Em um estilo de programação fluente, como o tipo comumente visto ao codificar com a nova API Java Streams, um resultado nulo em qualquer ponto faz com que o programa trave com uma NullPointerException. A
Optional
classe fornece um mecanismo para retornar resultados nulos para o código do cliente de uma forma que permite o estilo fluente sem causar o travamento do código do cliente.fonte
Se percorrermos o código de AbstractCollection.java em grepCode, que é uma classe ancestral para todas as implementações de coleção, isso nos ajudará a entender o significado dos métodos opcionais. Aqui está o código para o método add (e) na classe AbstractCollection. método add (e) é opcional de acordo com a interface de coleção
Método opcional significa que já está implementado em classes ancestrais e lança UnsupportedOperationException na chamada. Se quisermos tornar nossa coleção modificável, devemos substituir os métodos opcionais na interface da coleção.
fonte
Bem, este tópico foi abordado para ... sim ... mas pense, uma resposta está faltando. Estou falando sobre os "métodos padrão" de interfaces. Por exemplo, vamos imaginar que você terá uma classe para fechar qualquer coisa (como um destruidor ou algo assim). Digamos que deva ter 3 métodos. Vamos chamá-los de "doFirst ()", "doLast ()" e "onClose ()".
Portanto, dizemos que queremos que qualquer objeto desse tipo pelo menos realize "onClose ()", mas os outros são opcionais.
Você pode perceber isso, usando os "Métodos Padrão" das interfaces. Eu sei, isso na maioria das vezes negaria o motivo de uma interface, mas se você estiver projetando uma estrutura, isso pode ser útil.
Então, se você quiser perceber dessa forma, seria o seguinte
O que aconteceria agora, se você, por exemplo, implementasse em uma classe chamada "Teste", o compilador estaria perfeitamente bem com o seguinte:
com a saída:
ou
com a saída:
Todas as combinações são possíveis. Qualquer coisa com "padrão" pode ser implementada, mas não deve, no entanto, qualquer coisa sem deve ser implementada.
Espero que não esteja totalmente errado o que eu respondo agora.
Tenham todos um ótimo dia!
[edit1]: Observação: isso só funciona no Java 8.
fonte
Eu estava procurando uma maneira de implementar a interface de retorno de chamada, então a implementação de métodos opcionais era necessária, pois eu não queria implementar todos os métodos para cada retorno de chamada.
Então, em vez de usar uma interface, usei uma classe com implementação vazia, como:
E você pode definir a variável de membro CallBack assim,
em seguida, chame-o assim.
Dessa forma, você não precisa se preocupar em implementar todos os métodos por retorno de chamada, mas apenas sobrescrever aqueles de que você precisa.
fonte
Embora não responda à pergunta do OP, é importante notar que, a partir do Java 8, adicionar métodos padrão às interfaces é de fato factível . A
default
palavra-chave colocada na assinatura do método de uma interface resultará em uma classe com a opção de sobrescrever o método, mas não exigirá isso.fonte
Tutorial de coleções Java da Oracle:
fonte