Eu sei que não é possível definir um construtor em uma interface. Mas estou me perguntando por que, porque acho que poderia ser muito útil.
Portanto, você pode ter certeza de que alguns campos de uma classe são definidos para todas as implementações dessa interface.
Por exemplo, considere a seguinte classe de mensagem:
public class MyMessage {
public MyMessage(String receiver) {
this.receiver = receiver;
}
private String receiver;
public void send() {
//some implementation for sending the mssage to the receiver
}
}
Se definir uma interface para esta classe para que eu possa ter mais classes que implementam a interface da mensagem, só posso definir o método send e não o construtor. Então, como posso garantir que toda implementação dessa classe realmente tenha um receptor definido? Se eu usar um método como esse, setReceiver(String receiver)
não posso ter certeza de que esse método seja realmente chamado. No construtor, eu poderia garantir isso.
Respostas:
Tomando algumas das coisas que você descreveu:
... esses requisitos são exatamente para que servem as classes abstratas .
fonte
Message
interface que defina osend()
método, e se o Sebi desejar fornecer uma classe "base" para implementações daMessage
interface, forneçaAbstractMessage
também. As classes abstratas não devem substituir as interfaces, nunca tentaram sugerir isso.Um problema que você obtém ao permitir construtores em interfaces vem da possibilidade de implementar várias interfaces ao mesmo tempo. Quando uma classe implementa várias interfaces que definem diferentes construtores, a classe precisa implementar vários construtores, cada um satisfazendo apenas uma interface, mas não os outros. Será impossível construir um objeto que chame cada um desses construtores.
Ou no código:
fonte
class A implements Named, HashList { A(){HashList(new list()); Named("name");} }
new Set<Fnord>()
pudesse ser interpretado como "Dê-me algo que eu possa usar comoSet<Fnord>
"; se o autor deSet<T>
pretenderHashSet<T>
ser a implementação preferencial para coisas que não tinham uma necessidade específica de outra coisa, a interface poderia definirnew Set<Fnord>()
poderia ser considerada sinônimonew HashSet<Fnord>()
. Para uma classe implementar várias interfaces, isso não apresentaria nenhum problema, poisnew InterfaceName()
simplesmente construiria uma classe designada pela interface .A(String,List)
construtor pode ser o construtor designadoA(String)
eA(List)
pode ser secundário que o chama. Seu código não é um contra-exemplo, apenas um código ruim.Uma interface define um contrato para uma API, que é um conjunto de métodos com os quais o implementador e o usuário da API concordam. Uma interface não possui uma implementação instanciada, portanto, nenhum construtor.
O caso de uso que você descreve é semelhante a uma classe abstrata na qual o construtor chama um método de um método abstrato que é implementado em uma classe filho.
O problema inerente aqui é que, enquanto o construtor de base está sendo executado, o objeto filho ainda não foi construído e, portanto, em um estado imprevisível.
Resumindo: é pedir problemas quando você chama métodos sobrecarregados de construtores-pai, para citar mindprod :
fonte
Uma solução alternativa que você pode tentar é definir um
getInstance()
método em sua interface para que o implementador esteja ciente de quais parâmetros precisam ser manipulados. Não é tão sólido quanto uma classe abstrata, mas permite mais flexibilidade do que uma interface.No entanto, esta solução alternativa exige que você use o
getInstance()
para instanciar todos os objetos dessa interface.Por exemplo
fonte
Existem apenas campos estáticos na interface que não precisam ser inicializados durante a criação do objeto na subclasse e o método da interface deve fornecer implementação real na subclasse. Portanto, não há necessidade de construtor na interface.
Segunda razão: durante a criação do objeto da subclasse, o construtor pai é chamado. Mas, se houver mais de uma interface implementada, ocorrerá um conflito durante a chamada do construtor da interface sobre qual construtor da interface chamará primeiro
fonte
Se você deseja garantir que todas as implementações da interface contenham campos específicos, basta adicionar à sua interface o getter para esse campo :
Receiver
objeto deve ser passado para a classe de alguma forma (por construtor ou setter)fonte
Dependências que não são referenciadas nos métodos de uma interface devem ser consideradas como detalhes de implementação, não como algo que a interface impõe. É claro que pode haver exceções, mas, como regra, você deve definir sua interface como qual é o comportamento esperado. O estado interno de uma determinada implementação não deve ser uma preocupação de design da interface.
fonte
Veja esta pergunta para saber o porquê (retirado dos comentários).
Se você realmente precisar fazer algo assim, convém uma classe base abstrata em vez de uma interface.
fonte
Isso ocorre porque as interfaces não permitem definir o corpo do método nele. Mas devemos definir o construtor na mesma classe que as interfaces, por padrão, modificador abstrato para todos os métodos a serem definidos. É por isso que não podemos definir construtor nas interfaces.
fonte
Aqui está um exemplo usando esta técnica. Neste exemplo específico, o código está fazendo uma chamada para o Firebase usando uma simulação
MyCompletionListener
que é uma interface mascarada como uma classe abstrata, uma interface com um construtorfonte
private
modificador de acessointerface
?Geralmente os construtores são para inicializar membros não estáticos de uma classe específica em relação ao objeto.
Não há criação de objeto para interface, pois existem apenas métodos declarados, mas não métodos definidos. O motivo pelo qual não podemos criar objetos para métodos declarados é que a criação de objetos nada mais é do que alocar memória (na memória heap) para membros não estáticos.
A JVM criará memória para membros totalmente desenvolvidos e prontos para uso. Com base nesses membros, a JVM calcula a quantidade de memória necessária para eles e cria memória.
No caso de métodos declarados, a JVM não consegue calcular a quantidade de memória necessária para esses métodos declarados, pois a implementação será no futuro, o que não será feito até o momento. portanto, a criação de objetos não é possível para a interface.
conclusão:
sem a criação do objeto, não há chance de inicializar membros não estáticos por meio de um construtor. É por isso que o construtor não é permitido dentro de uma interface. (como não há uso do construtor dentro de uma interface)
fonte