假设我有这些接口:
public interface I1 {
void foo();
}
public interface I2 {
void bar();
}
和班级:
public class A extends AParent implements I1, I2 {
// code for foo and bar methods here
}
public class B extends BParent implements I1, I2 {
// code for foo and bar methods here
}
public class C extends CParent implements I1 {
// code for foo method here
}
现在,使用泛型,我可以使用以下方法:
public <T extends I1 & I2> void method(T param) {
param.foo();
param.bar();
}
我可以用A和B作为参数调用它,但不能用C调用它(它没有实现I2)。
有没有办法实现这种类型的安全预先通用(java&lt; 1.5)。
考虑到A,B和C具有不同的继承树,并且实际上不能选择像父母一样拥有共同父级的AParent和BParent。
我知道你可以这样做:
public void method(I1 param) {
param.foo();
((I2)param).bar();
}
但是你也可以打电话给那些没有实现I2的method(new C())
,这样你就会遇到麻烦。
那么你有没有其他方法可以做到这一点?
P.S。 :我真的不需要这样做,这主要是出于我的好奇心。
答案 0 :(得分:24)
创建第三个接口I3扩展I1和I2。然后A类和B类都实现I3,泛型方法接受I3。
这可能是唯一的方法。
答案 1 :(得分:12)
我不认为上述答案在设计观点下是好的。创建界面时,您希望确保调用者对象对该界面中定义的某些操作具有职责。所以上面讨论了两个解决方案,我将告诉为什么这些解决方案在设计方面并不好。
<强> 1。使一个接口扩展到两个接口:
public interface IC extends IA,IB {
// empty method here
}
以上代码是无意义的。您只需要组合一个单独的接口来组合其他接口,并且内部没有任何新方法。您不会向IC
添加任何值,而不是将两个界面IA
和IB
结合使用。在某些情况下,当您找不到第三个界面的合适名称时,这种方式会使您的代码“变得有趣”。这种情况会导致某些界面名称,例如IReadableAndWriteable
或ISomethingAndSomethingAndAnotherThing
<强> 2。在方法内输入:
public void methodA(IA object) {
if (object instance of IB) {
((IB)(object)).someMethod()
}
这种方式也是无稽之谈。为什么输入参数为IA
,那么您必须从接口IB
执行某些操作?在程序员的观点下,除了阅读你的文档之外,没有办法知道这一点。这对于设计其他人使用的功能并不好。
真正的解决方案:
以上解决方案在设计中存在另一个问题:您强制程序员使用一个负责两个接口的对象。如果程序员不想这样做会有什么问题。他们想为每个不同的接口使用两个不同的混凝土类,以便于测试,清洁代码? 他们不能。
您应该在方法签名中创建两个不同的参数:
public void exampleMethod(IA object1, IB object2) {
object1.someMethod()
object2.someMethod()
}
为了调用上面的方法,你把相同的参数放在里面(如果程序员使用相同的对象)。它们也可以放置不同的物体。
public void caller() {
IC object3 = new C(); // C is the class implements both IA and IB
exampleMethod(object3, object3);
IA objectA = new A();
IB objectB = new B();
exampleMethod(objectA, objectB);
}
希望这有帮助:)
答案 2 :(得分:2)
在Java 1.5之前,IMO没有解决方案来在编译时实现这种类型安全性。但是在运行时使用“instanceof”有一个解决方案。
public void method(Object o) {
if (!(o instanceof I1))
throw new RuntimeException("o is not instance of I1");
if (!(o instanceof I2))
throw new RuntimeException("o is not instance of I2");
// go ahead ...
}
答案 3 :(得分:2)
sri是最好的答案。但是,如果你没有获得许可,那么你可以做到:
public void method(I1 param1 , I2 param2) { // unpopular classes that do not implement I3 must use this method
param1.foo();
param2.bar();
}
public void method(I3 param){ // I hope everybody implements I3 when appropriate
param.foo();
param.bar();
}
public void method(A param){// A is a popular class
method(param,param);
}
public void method(B param){// B is a popular class
method(param,param);
}
当然,现在只使用泛型。