如果我有两个接口,它们的目的非常不同,但是方法签名相同,那么如何使一个类同时实现这两个接口,而不被迫编写为两个接口服务的单个方法,并在方法实现中编写一些复杂的逻辑以检查调用所针对的对象类型并调用正确的代码?
在C#中,可以通过显式接口实现来解决这个问题。在Java中是否有任何等效的方法?
如果我有两个接口,它们的目的非常不同,但是方法签名相同,那么如何使一个类同时实现这两个接口,而不被迫编写为两个接口服务的单个方法,并在方法实现中编写一些复杂的逻辑以检查调用所针对的对象类型并调用正确的代码?
在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();}
}
ISomething1 CompositeClass.asInterface1();
和一个ISomething2 CompositeClass.asInterface2();
方法。然后你可以从复合类中获取一个或另一个。但是这个问题没有很好的解决方案。 - jjnguypublic long getCountAsLong() implements interface2.getCount {...}
这样允许的话,会有多么混乱呢?或者假设collectionInterface
有一个canAdd()
方法,并且对于该类的所有实例它都返回false
,那么private void AddStub(T newObj) implements coolectionInterface.Add
又该如何处理呢? - supercat在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()
};
}
}
虽然它不允许从AlfaBeta
转换为Beta
,但向下转型通常是不好的。如果可以预期到一个Alfa
实例往往也具有Beta
方面,并且出于某种原因(通常是优化是唯一有效的原因),您想将其转换为Beta
,则可以创建一个Alfa
子接口,其中包含Beta asBeta()
。
如果你遇到这个问题,很可能是因为你在应该使用委托的地方使用了继承。如果你需要为相同的底层数据模型提供两个不同但类似的接口,那么你应该使用视图来以一种廉价的方式提供对数据的访问。
举个具体的例子,假设你想要实现Collection
和MyCollection
(它不继承自Collection
并且具有不兼容的接口)。你可以提供Collection getCollectionView()
和MyCollection getMyCollectionView()
函数,使用相同的底层数据提供Collection
和MyCollection
的轻量级实现。
对于前面的情况... 假设你确实需要一个整数数组和一个字符串数组。你应该拥有一个类型为List<Integer>
的成员和一个类型为List<String>
的成员,并引用这些成员,而不是尝试从两者都继承。即使你只需要一个整数列表,也最好在这种情况下使用组合/委托而不是继承。
public interface Framework1Interface {
void method(Object o);
}
and
public interface Framework2Interface {
void method(Object o);
}
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*方法来“公开”您的类
当你完全控制所涉及的所有代码并可以事先实现时,一切都很好。 现在想象一下,你有一个现有的公共类,在许多地方使用一个方法。
public class MyClass{
private String name;
MyClass(String name){
this.name = name;
}
public String getName(){
return name;
}
}
现在你需要将它传递给现成的WizzBangProcessor,该处理器需要类来实现WBPInterface...该接口还有一个getName()方法,但是与您的具体实现不同,该接口期望该方法返回一种Wizz Bang Processing类型的名称。
在C#中,这将是一个微不足道的事情。
public class MyClass : WBPInterface{
private String name;
String WBPInterface.getName(){
return "MyWizzBangProcessor";
}
MyClass(String name){
this.name = name;
}
public String getName(){
return name;
}
}
SampleClass:IControl,ISurface
,每个接口都定义了一个Paint
方法的示例:https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/explicit-interface-implementation - j00hi