使用实现多个接口预泛型的参数

假设我有这些接口:

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

那么,还有其他方法可以做到这一点吗?

P.S. :我真的不需要这样做,我问这主要是出于好奇。


答案 1

创建第三个接口 I3 扩展 I1 和 I2。然后,类 A 和 B 都实现 I3,泛型方法接受 I3。

这也许是唯一的方法。


答案 2

我不认为上面的答案在设计观点下是好的。创建接口时,需要确保调用方对象负责该接口中定义的某些操作。因此,上面讨论了两种解决方案,我将说明为什么这些解决方案在设计角度来看并不好。

1. 使一个接口扩展两个接口:

public interface IC extends IA,IB {
   // empty method here
}

上面的代码是无意义的。您定义一个单独的接口只是为了组合其他接口,并且内部没有任何新方法。您不添加任何值,而是将两个接口 和 组合在一起。在某些情况下,当您找不到适合第三个接口的名称时,这种方式会使您的代码“小玩意”。这种情况将导致一些接口名称,例如或ICIAIBIReadableAndWriteableISomethingAndSomethingAndAnotherThing

2.类型铸造内部方法:

public void methodA(IA object) {
   if (object instance of IB) {
     ((IB)(object)).someMethod()
}

这种方式也是无稽之谈。为什么输入参数是你必须从接口执行一些操作?在程序员的视角下,除了阅读文档之外,没有办法知道这一点。这不利于设计供其他人使用的功能。IAIB

真正的解决方案:

上述解决方案在设计中还有另一个问题:您强制程序员使用一个负责两个接口的对象。如果程序员不想这样做,那有什么问题呢?他们想为每个不同的接口使用两个不同的具体类,以便于测试,干净的代码?他们不能。

您应该在方法签名中创建两个不同的参数:

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

希望这有帮助:)