Java – colisão de nome de método na implementação de interface

Se eu tiver duas interfaces, ambas bem diferentes em seus propósitos, mas com a mesma assinatura de método, como faço uma class implementar ambas sem ser forçada 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 qual tipo de object a chamada está sendo feita e invoca o código correto?

Em C #, isso é superado pelo que é chamado de implementação de interface explícita. Existe alguma maneira equivalente em Java?

Não, não há como implementar o mesmo método de duas maneiras diferentes em uma class em Java.

Isso pode levar a muitas situações confusas, e é por isso que o Java não permitiu isso.

interface ISomething { void doSomething(); } interface ISomething2 { void doSomething(); } class Impl implements ISomething, ISomething2 { void doSomething() {} // There can only be one implementation of this method. } 

O que você pode fazer é compor uma class de duas classs, cada uma implementando uma interface diferente. Então essa class terá o comportamento de ambas as interfaces.

 class CompositeClass { ISomething class1; ISomething2 class2; void doSomething1(){class1.doSomething();} void doSomething2(){class2.doSomething();} } 

Não há uma maneira real de resolver isso em Java. Você poderia usar classs internas como uma solução alternativa:

 interface Alfa { void m(); } interface Beta { void m(); } class AlfaBeta implements Alfa { private int value; public void m() { ++value; } // Alfa.m() public Beta asBeta() { return new Beta(){ public void m() { --value; } // Beta.m() }; } } 

Embora não permita lançamentos do AlfaBeta para o Beta , os downcasts são geralmente ruins, e se é de se esperar que uma instância do Alfa também tenha um aspecto Beta , e por algum motivo (geralmente a otimização é o único motivo válido) você quer ser capaz de convertê-lo para Beta , você poderia fazer uma sub-interface do Alfa com o Beta asBeta() nele.

Se você está encontrando este problema, é mais provável porque você está usando a inheritance onde você deve estar usando a delegação . Se você precisar fornecer duas interfaces diferentes, embora semelhantes, para o mesmo modelo subjacente de dados, deverá usar uma visualização para fornecer access mais barato aos dados usando alguma outra interface.

Para dar um exemplo concreto para o último caso, suponha que você queira implementar Collection e MyCollection (que não herda de Collection e tem uma interface incompatível). Você poderia fornecer uma Collection getCollectionView() e MyCollection getMyCollectionView() funções que fornecem uma implementação leve de Collection e MyCollection , usando os mesmos dados subjacentes.

Para o primeiro caso … suponha que você realmente deseja uma matriz de números inteiros e uma matriz de seqüências de caracteres. Em vez de herdar de List e List , você deve ter um membro do tipo List e outro membro do tipo List e referir-se a esses membros, em vez de tentar herdar de ambos. Mesmo se você só precisasse de uma lista de números inteiros, é melhor usar composição / delegação sobre inheritance nesse caso.

O problema “clássico” de Java também afeta meu desenvolvimento Android …
O motivo parece ser simples:
Mais frameworks / bibliotecas você tem que usar, mais facilmente as coisas podem estar fora de controle …

No meu caso, eu tenho uma class BootStrapperApp herdada de android.app.Application ,
enquanto a mesma class também deve implementar uma interface de plataforma de uma estrutura de MVVM para se integrar.
A colisão de método ocorreu em um método getString () , que é anunciado por ambas as interfaces e deve ter implementação diferenciada em diferentes contextos.
A solução alternativa (feia..IMO) está usando uma class interna para implementar todos os methods da Plataforma , apenas por causa de um conflito de assinatura de método menor … em alguns casos, esse método emprestado nem sequer é usado (mas afetou a semântica principal do projeto) .
Eu tendo a concordar que a indicação explícita do contexto / espaço de nomes no estilo do C # é útil.

A única solução que me veio à mente é usar objects de referência para o que você deseja implantar várias interfaces.

por exemplo: supondo que você tenha 2 interfaces para implementar

 public interface Framework1Interface { void method(Object o); } 

e

 public interface Framework2Interface { void method(Object o); } 

você pode colocá-los em dois objects do Facador:

 public class Facador1 implements Framework1Interface { private final ObjectToUse reference; public static Framework1Interface Create(ObjectToUse ref) { return new Facador1(ref); } private Facador1(ObjectToUse refObject) { this.reference = refObject; } @Override public boolean equals(Object obj) { if (obj instanceof Framework1Interface) { return this == obj; } else if (obj instanceof ObjectToUse) { return reference == obj; } return super.equals(obj); } @Override public void method(Object o) { reference.methodForFrameWork1(o); } } 

e

 public class Facador2 implements Framework2Interface { private final ObjectToUse reference; public static Framework2Interface Create(ObjectToUse ref) { return new Facador2(ref); } private Facador2(ObjectToUse refObject) { this.reference = refObject; } @Override public boolean equals(Object obj) { if (obj instanceof Framework2Interface) { return this == obj; } else if (obj instanceof ObjectToUse) { return reference == obj; } return super.equals(obj); } @Override public void method(Object o) { reference.methodForFrameWork2(o); } } 

No final, a aula que você queria deveria ser algo como

 public class ObjectToUse { private Framework1Interface facFramework1Interface; private Framework2Interface facFramework2Interface; public ObjectToUse() { } public Framework1Interface getAsFramework1Interface() { if (facFramework1Interface == null) { facFramework1Interface = Facador1.Create(this); } return facFramework1Interface; } public Framework2Interface getAsFramework2Interface() { if (facFramework2Interface == null) { facFramework2Interface = Facador2.Create(this); } return facFramework2Interface; } public void methodForFrameWork1(Object o) { } public void methodForFrameWork2(Object o) { } } 

Agora você pode usar os methods getAs * para “expor” sua turma

Você pode usar um padrão de adaptador para fazer isso funcionar. Crie dois adaptadores para cada interface e use isso. Deve resolver o problema.

Tudo bem e 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 class pública existente usada em muitos lugares com um método

 public class MyClass{ private String name; MyClass(String name){ this.name = name; } public String getName(){ return name; } } 

Agora você precisa passá-lo na prateleira WizzBangProcessor que requer classs para implementar o WBPInterface … que também tem um método getName (), mas em vez de sua implementação concreta, essa interface espera que o método retorne o nome de um tipo de Wizz Bang Processing.

Em C # seria um trvial

 public class MyClass : WBPInterface{ private String name; String WBPInterface.getName(){ return "MyWizzBangProcessor"; } MyClass(String name){ this.name = name; } public String getName(){ return name; } } 

No Java Tough, você terá que identificar cada ponto na base de código implantada existente na qual você precisa converter de uma interface para outra. Claro que 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 class que corresponde à assinatura deste método nesta interface implementada é sua implementação”. Afinal, todo o objective de definir interfaces é permitir que a definição seja abstraída da implementação. (Nem mesmo comecei a ter methods padrão em Interfaces em Java, e muito menos a substituição padrão … porque, com certeza, todos os componentes projetados para um carro de estrada deveriam ser acionados em um carro voador e simplesmente funcionar – ei Ambos são carros … Eu tenho certeza que a funcionalidade padrão de dizer o seu nav sentado não será afetado com inputs padrão de arremesso e rolo, porque os carros só guinam!

Intereting Posts