Java – 接口实现中的方法名称冲突

如果我有两个接口,它们的目的完全不同,但是具有相同的方法签名,我怎样才能使一个类实现,而不必强制为这两个接口编写一个方法,并在方法中编写一些复杂的逻辑实现,检查哪种types的对象正在进行调用,并调用正确的代码?

在C#中,这被所谓的显式接口实现所克服。 在Java中有没有等价的方法?

不,在Java的一个类中,没有办法以两种不同的方式实现相同的方法。

这可能会导致许多令人困惑的情况,这就是Java拒绝它的原因。

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

你可以做的是从两个类中组成一个类,每个类实现不同的接口。 那么一个类将具有这两个接口的行为。

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

在Java中没有真正的解决方法。 你可以使用内部类作为解决方法:

 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() }; } } 

虽然它不允许从AlfaBetaBeta转换,但是向下转换通常是邪恶的,如果可以预期的话, Alfa实例通常也有一个Beta方面,并且出于某种原因(通常优化是唯一正当的理由)希望能够将其转换为Beta ,您可以在其中创build一个Alfa的子接口Beta asBeta()

如果遇到这个问题,很可能是因为您在应该使用委派的地方使用inheritance 。 如果您需要为相同的基础数据模型提供两个不同但类似的接口,那么您应该使用一个视图以便宜的方式提供对其他接口的访问。

为了给出后一种情况的一个具体的例子,假设你想实现Collection和MyCollection(它不能从Collectioninheritance并且有一个不兼容的接口)。 您可以使用相同的基础数据提供“Collection getCollectionView()”和“MyCollection getMyCollectionView()”函数,它们提供了Collection和MyCollection的轻量级实现。

对于前一种情况…假设你真的需要一个整数数组和string数组。 您应该有一个List <Integer>types的成员和另一个List <String>types的成员,而不是从List <Integer>和List <String>inheritance,而是从这两个成员inheritance。 即使你只需要一个整数列表,在这种情况下最好使用inheritance的组合/委托。

“古典”的Java问题也影响到我的Android开发…
原因似乎很简单:
你必须使用更多的框架/库,更容易的事情可能会失控…

在我的情况下,我有一个从android.app.Applicationinheritance的BootStrapperApp类,
而同一个类也应该实现一个MVVM框架的Platform接口以便集成。
方法碰撞发生在一个getString()方法上,这个方法由两个接口公布,并且应该在不同的上下文中有不同的实现。
解决scheme(ugly..IMO)使用一个内部类来实现所有的Platform方法,只是因为一个小的方法签名冲突…在某些情况下,这样的借用方法甚至根本不用(但是影响了主要的devise语义) 。
我倾向于同意C#风格的显式上下文/名称空间指示是有帮助的。

我想到的唯一解决scheme是将引用对象用于要实现多个接口的对象。

例如:假设你有2个接口来实现

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

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

你可以把它们放在两个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); } } 

 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); } } 

最后,你想要的类应该像

 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) { } } 

你现在可以使用getAs *方法来“暴露”你的课程

您可以使用适配器模式来使这些工作。 为每个接口创build两个适配器并使用它。 它应该解决这个问题。

当你完全控制所有有关的代码并且可以实现这一点的时候,一切顺利。 现在想象一下,在一个方法的许多地方使用现有的公共类

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

现在你需要把它传递给现成的WizzBangProcessor,它需要类来实现WBPInterface …它也有一个getName()方法,但是这个接口不是你的具体实现,而是期望方法返回一个types的名字Wizz Bang处理。

在C#中,这将是一个小问题

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

在Java中,您需要确定现有已部署的代码库中的每个点,您需要从一个接口转换到另一个接口。 当然WizzBangProcessor公司应该使用getWizzBangProcessName(),但他们也是开发者。 在他们的上下文getName是好的。 实际上,在Java之外,大多数其他基于OO的语言都支持这一点。 Java在使用相同的方法NAME强制所有接口都很less见。

大多数其他语言有一个编译器,非常乐意接受指令说:“这个类中的这个方法匹配这个方法在这个实现的接口中的签名是它的实现”。 毕竟定义接口的全部要点是允许定义从实现中抽象出来。 (甚至不要让我开始在Java中的Interfaces中使用默认方法,更不要说默认覆盖…因为当然,为道路汽车devise的每个组件都应该能够撞上一辆飞行汽车,并且只是工作 – 嘿他们都是汽车…我敢肯定默认的function说你的卫星导航将不会受到默认的音调和滚动input的影响,因为汽车只偏航!