Java - 接口实现中的方法名称冲突
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2598009/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java - Method name collision in interface implementation
提问by Bhaskar
If I have two interfaces , both quite different in their purposes , but with same method signature , how do I make a class implement both without being forced to write a single method that serves for the both the interfaces and writing some convoluted logic in the method implementation that checks for which type of object the call is being made and invoke proper code ?
如果我有两个接口,它们的目的完全不同,但具有相同的方法签名,我如何让一个类实现这两个接口,而不必被迫编写为这两个接口提供服务的单个方法,并在方法中编写一些复杂的逻辑?检查正在调用的对象类型并调用正确代码的实现?
In C# , this is overcome by what is called as explicit interface implementation. Is there any equivalent way in Java ?
在 C# 中,这可以通过所谓的显式接口实现来克服。Java 中是否有任何等效的方法?
采纳答案by jjnguy
No, there is no way to implement the same method in two different ways in one class in Java.
不,没有办法在 Java 的一个类中以两种不同的方式实现相同的方法。
That can lead to many confusing situations, which is why Java has disallowed it.
这会导致许多令人困惑的情况,这就是 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.
}
What you can do is compose a class out of two classes that each implement a different interface. Then that one class will have the behavior of both interfaces.
您可以做的是将两个类组合成一个类,每个类都实现不同的接口。那么一个类将具有两个接口的行为。
class CompositeClass {
ISomething class1;
ISomething2 class2;
void doSomething1(){class1.doSomething();}
void doSomething2(){class2.doSomething();}
}
回答by Michael Aaron Safyan
If you are encountering this problem, it is most likely because you are using inheritancewhere you should be using delegation. If you need to provide two different, albeit similar, interfaces for the same underlying model of data, then you should use a viewto cheaply provide access to the data using some other interface.
如果您遇到此问题,很可能是因为您在应该使用委托的地方使用了继承。如果您需要为相同的底层数据模型提供两个不同但相似的接口,那么您应该使用视图来廉价地使用其他接口提供对数据的访问。
To give a concrete example for the latter case, suppose you want to implement both Collection
and MyCollection
(which does not inherit from Collection
and has an incompatible interface). You could provide a Collection getCollectionView()
and MyCollection getMyCollectionView()
functions which provide a light-weight implementation of Collection
and MyCollection
, using the same underlying data.
为后一种情况提供一个具体示例,假设您要同时实现Collection
and MyCollection
(它不继承自Collection
且具有不兼容的接口)。你可以提供一个Collection getCollectionView()
和MyCollection getMyCollectionView()
其提供了重量轻的执行功能Collection
和MyCollection
使用相同的基础数据。
For the former case... suppose you really want an array of integers and an array of strings. Instead of inheriting from both List<Integer>
and List<String>
, you should have one member of type List<Integer>
and another member of type List<String>
, and refer to those members, rather than try to inherit from both. Even if you only needed a list of integers, it is better to use composition/delegation over inheritance in this case.
对于前一种情况......假设你真的想要一个整数数组和一个字符串数组。相反,来自继承的List<Integer>
和List<String>
,你应该有类型的一个成员List<Integer>
和类型的其他成员List<String>
,并从两个指那些成员,而不是试图继承。即使您只需要一个整数列表,在这种情况下最好使用组合/委托而不是继承。
回答by gustafc
There's no real way to solve this in Java. You could use inner classes as a workaround:
在 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()
};
}
}
Although it doesn't allow for casts from AlfaBeta
to Beta
, downcasts are generally evil, and if it can be expected that an Alfa
instance often has a Beta
aspect, too, and for some reason (usually optimization is the only valid reason) you want to be able to convert it to Beta
, you could make a sub-interface of Alfa
with Beta asBeta()
in it.
虽然它不允许从AlfaBeta
to进行强制转换Beta
,但向下转换通常是邪恶的,如果可以预期Alfa
实例通常也有一个Beta
方面,并且出于某种原因(通常优化是唯一有效的原因),您希望能够要将其转换为Beta
,您可以在其中创建一个Alfa
with子接口Beta asBeta()
。
回答by tiancheng
The "classical" Java problem also affects my Android development...
The reason seems to be simple:
More frameworks/libraries you have to use, more easily things can be out of control...
In my case, I have a BootStrapperAppclass inherited from android.app.Application,
whereas the same class should also implement a Platforminterface of a MVVM framework in order to get integrated.
Method collision occurred on a getString()method, which is announced by both interfaces and should have differenet implementation in different contexts.
The workaround (ugly..IMO) is using an inner class to implement all Platformmethods, just because of one minor method signature conflict...in some case, such borrowed method is even not used at all (but affected major design semantics).
I tend to agree C#-style explicit context/namespace indication is helpful.
“经典”Java 问题也影响了我的 Android 开发...
原因似乎很简单:
您必须使用更多框架/库,更容易使事情失控...
在我的情况下,我有一个BootStrapperApp类继承自android.app.Application,
而同一个类还应该实现MVVM 框架的Platform接口才能集成。
方法冲突发生在getString()方法上,该方法由两个接口声明并且在不同的上下文中应该有不同的实现。
解决方法(丑陋..IMO)使用内部类来实现所有平台方法,只是因为一个次要的方法签名冲突……在某些情况下,甚至根本不使用这种借用的方法(但影响了主要的设计语义)。
我倾向于同意 C# 风格的显式上下文/命名空间指示是有帮助的。
回答by notAtAll
The only solution that came in my mind is using referece objects to the one you want to implent muliple interfaceces.
我想到的唯一解决方案是使用引用对象来实现多个接口。
eg: supposing you have 2 interfaces to implement
例如:假设您有 2 个接口要实现
public interface Framework1Interface {
void method(Object o);
}
and
和
public interface Framework2Interface {
void method(Object o);
}
you can enclose them in to two Facador objects:
您可以将它们包含在两个 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);
}
}
and
和
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);
}
}
In the end the class you wanted should something like
最后,您想要的课程应该类似于
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) {
}
}
you can now use the getAs* methods to "expose" your class
您现在可以使用 getAs* 方法来“公开”您的课程
回答by AlexCon
You can use an Adapter pattern in order to make these work. Create two adapter for each interface and use that. It should solve the problem.
您可以使用适配器模式来使这些工作。为每个接口创建两个适配器并使用它。它应该可以解决问题。
回答by user8232920
All well and good when you have total control over all of the code in question and can implement this upfront. Now imagine you have an existing public class used in many places with a method
当您完全控制所有相关代码并且可以预先实现这一点时,一切都很好。现在想象你有一个现有的公共类,在很多地方都使用了一个方法
public class MyClass{
private String name;
MyClass(String name){
this.name = name;
}
public String getName(){
return name;
}
}
Now you need to pass it into the off the shelf WizzBangProcessor which requires classes to implement the WBPInterface... which also has a getName() method, but instead of your concrete implementation, this interface expects the method to return the name of a type of Wizz Bang Processing.
现在您需要将它传递到现成的 WizzBangProcessor 中,它需要类来实现 WBPInterface ......它也有一个 getName() 方法,但不是您的具体实现,这个接口期望该方法返回一个类型的名称的 Wizz Bang 处理。
In C# it would be a trvial
在 C# 中,这将是一个微不足道的
public class MyClass : WBPInterface{
private String name;
String WBPInterface.getName(){
return "MyWizzBangProcessor";
}
MyClass(String name){
this.name = name;
}
public String getName(){
return name;
}
}
In Java Tough you are going to have to identify every point in the existing deployed code base where you need to convert from one interface to the other. Sure the WizzBangProcessor company should have used getWizzBangProcessName(), but they are developers too. In their context getName was fine. Actually, outside of Java, most other OO based languages support this. Java is rare in forcing all interfaces to be implemented with the same method NAME.
在 Java Tough 中,您将必须确定现有已部署代码库中需要从一种接口转换为另一种接口的每一点。当然,WizzBangProcessor 公司应该使用 getWizzBangProcessName(),但他们也是开发人员。在他们的上下文中 getName 很好。实际上,在 Java 之外,大多数其他基于 OO 的语言都支持这一点。Java 很少强制所有接口都使用相同的方法 NAME 来实现。
Most other languages have a compiler that is more than happy to take an instruction to say "this method in this class which matches the signature of this method in this implemented interface is it's implementation". After all the whole point of defining interfaces is to allow the definition to be abstracted from the implementation. (Don't even get me started on having default methods in Interfaces in Java, let alone default overriding.... because sure, every component designed for a road car should be able to get slammed into a flying car and just work - hey they are both cars... I'm sure the the default functionality of say your sat nav will not be affected with default pitch and roll inputs, because cars only yaw!
大多数其他语言都有一个编译器,它很乐意接受一条指令,说“这个类中的这个方法与这个实现的接口中的这个方法的签名相匹配是它的实现”。毕竟,定义接口的全部意义在于允许从实现中抽象出定义。(甚至不要让我开始在 Java 的接口中使用默认方法,更不用说默认覆盖了......因为当然,为公路车设计的每个组件都应该能够撞上飞行的汽车并正常工作 - 嘿它们都是汽车......我确信默认的卫星导航功能不会受到默认俯仰和滚转输入的影响,因为汽车只会偏航!