Se eu tenho duas interfaces, ambas bastante diferentes em seus propósitos, mas com a mesma assinatura de método, como faço para fazer uma classe implementar ambas sem ser forçado a escrever um único método que sirva para ambas as interfaces e escrever alguma lógica complicada no método implementação que verifica para qual tipo de objeto a chamada está sendo feita e invoca o código adequado?
Em C #, isso é superado pelo que é chamado de implementação de interface explícita. Existe alguma forma equivalente em Java?
Respostas:
Não, não há como implementar o mesmo método de duas maneiras diferentes em uma classe em Java.
Isso pode levar a muitas situações confusas, e é por isso que Java não permite isso.
O que você pode fazer é compor uma classe de duas classes, cada uma implementando uma interface diferente. Então, essa classe terá o comportamento de ambas as interfaces.
fonte
ISomething1 CompositeClass.asInterface1();
eISomething2 CompositeClass.asInterface2();
a essa classe. Em seguida, você pode obter apenas um ou outro da classe composta. No entanto, não existe uma grande solução para este problema.public long getCountAsLong() implements interface2.getCount {...}
[no caso de a interface requerer umlong
mas os usuários da classe esperamint
] ouprivate void AddStub(T newObj) implements coolectionInterface.Add
[assumindo quecollectionInterface
tem umcanAdd()
método, e para todas as instâncias desta classe ele retornafalse
]?Não há uma maneira real de resolver isso em Java. Você pode usar classes internas como uma solução alternativa:
Embora não permita conversões de
AlfaBeta
paraBeta
, downcasts geralmente são ruins e, se for esperado que umaAlfa
instância também tenha umBeta
aspecto, por algum motivo (geralmente a otimização é o único motivo válido), você deseja poder para convertê-loBeta
, você poderia fazer uma subinterfaceAlfa
comBeta asBeta()
nele.fonte
Se você estiver encontrando esse problema, é mais provável que esteja usando herança, onde deveria usar delegação . Se você precisar fornecer duas interfaces diferentes, embora semelhantes, para o mesmo modelo de dados subjacente, você deve usar uma visualização para fornecer acesso aos dados de maneira econômica usando alguma outra interface.
Para dar um exemplo concreto para o último caso, suponha que você deseja implementar
Collection
eMyCollection
(que não herda deCollection
e tem uma interface incompatível). Você pode fornecer funções aCollection getCollectionView()
eMyCollection getMyCollectionView()
que fornecem uma implementação leve deCollection
eMyCollection
, usando os mesmos dados subjacentes.Para o primeiro caso ... suponha que você realmente queira um array de inteiros e um array de strings. Em vez de herdar de ambos
List<Integer>
eList<String>
, você deve ter um membro do tipoList<Integer>
e outro membro do tipoList<String>
e referir-se a esses membros, em vez de tentar herdar de ambos. Mesmo que você precise apenas de uma lista de inteiros, é melhor usar composição / delegação sobre herança neste caso.fonte
O problema "clássico" do Java também afeta meu desenvolvimento Android ...
A razão parece ser simples:
mais frameworks / bibliotecas que você tem que usar, mais facilmente as coisas podem ficar fora de controle ...
No meu caso, eu tenho uma classe BootStrapperApp herdado de android.app.Application ,
enquanto a mesma classe também deve implementar uma interface de plataforma de uma estrutura MVVM para ser integrada.
A colisão de métodos ocorreu em um método getString () , que é anunciado por ambas as interfaces e deve ter implementação diferente em contextos diferentes.
A solução alternativa (feio..IMO) é usar uma classe interna para implementar todas as plataformasmétodos, apenas por causa de um conflito menor de assinatura de método ... em alguns casos, tal método emprestado nem mesmo é usado (mas afetou a semântica de design principal).
Eu tendo a concordar que a indicação explícita de contexto / namespace no estilo C # é útil.
fonte
A única solução que me veio à mente é usar objetos de referência para aquele que você deseja implantar interfaces múltiplas.
por exemplo: supondo que você tenha 2 interfaces para implementar
e
você pode agrupá-los em dois objetos Facador:
e
No final, a aula que você queria deve algo como
agora você pode usar os métodos getAs * para "expor" sua classe
fonte
Você pode usar um padrão Adaptador para fazer isso funcionar. Crie dois adaptadores para cada interface e use-os. Deve resolver o problema.
fonte
Tudo bem quando você tem controle total sobre todo o código em questão e pode implementar isso antecipadamente. Agora imagine que você tem uma classe pública existente usada em muitos lugares com um método
Agora você precisa passá-lo para o WizzBangProcessor de prateleira, que requer classes para implementar a WBPInterface ... que também tem um método getName (), mas em vez de sua implementação concreta, esta interface espera que o método retorne o nome de um tipo do processamento Wizz Bang.
Em C # seria um trvial
Em Java Tough, você terá que identificar cada ponto na base de código implementado existente onde você precisa converter de uma interface para outra. Claro, a empresa WizzBangProcessor deveria ter usado getWizzBangProcessName (), mas eles também são desenvolvedores. Em seu contexto, getName estava bem. Na verdade, fora do Java, a maioria das outras linguagens baseadas em OO suportam isso. Java é raro em forçar todas as interfaces a serem implementadas com o mesmo método NAME.
A maioria das outras linguagens tem um compilador que fica mais do que feliz em receber uma instrução para dizer "este método nesta classe que corresponde à assinatura deste método nesta interface implementada é a sua implementação". Afinal, o objetivo da definição de interfaces é permitir que a definição seja abstraída da implementação. (Nem me fale sobre como ter métodos padrão em Interfaces em Java, muito menos sobreposição padrão ... porque com certeza, cada componente projetado para um carro de estrada deve ser capaz de bater em um carro voador e apenas funcionar - ei ambos são carros ... Tenho certeza que a funcionalidade padrão de digamos que seu navegador por satélite não será afetado com as entradas padrão de pitch e roll, porque os carros apenas guinam!
fonte