[英]Using parameter that implements multiple interfaces pre-generics
假设我有这些接口:
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 <1.5)。
考虑到A,B和C具有不同的继承树,并且实际上不能选择像父母一样拥有共同父级的AParent和BParent。
我知道你可以这样做:
public void method(I1 param) {
param.foo();
((I2)param).bar();
}
但是你也可以调用没有实现I2的method(new C())
,所以你遇到了麻烦。
那么你有没有其他方法可以做到这一点?
PS:我真的不需要这样做,这主要是出于好奇,我问。
创建第三个接口I3扩展I1和I2。 然后A类和B类都实现I3,泛型方法接受I3。
这可能是唯一的方法。
我不认为上述答案在设计观点下是好的。 在创建接口时,您希望确保调用者对象对该接口中定义的某些操作负责 。 所以上面讨论了两种解决方案,我将告诉为什么这些解决方案在设计方面并不好。
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);
}
希望这有帮助:)
在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 ...
}
如果您有权更改A和B的签名,则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);
}
当然,现在只使用泛型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.