使用实现多个接口pre-generics的参数

时间:2010-06-24 08:07:39

标签: java generics parameters multiple-inheritance

假设我有这些接口:

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。 :我真的不需要这样做,这主要是出于我的好奇心。

4 个答案:

答案 0 :(得分:24)

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

这可能是唯一的方法。

答案 1 :(得分:12)

我不认为上述答案在设计观点下是好的。创建界面时,您希望确保调用者对象对该界面中定义的某些操作具有职责。所以上面讨论了两个解决方案,我将告诉为什么这些解决方案在设计方面并不好。

<强> 1。使一个接口扩展到两个接口:

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

以上代码是无意义的。您只需要组合一个单独的接口来组合其他接口,并且内部没有任何新方法。您不会向IC添加任何值,而不是将两个界面IAIB结合使用。在某些情况下,当您找不到第三个界面的合适名称时,这种方式会使您的代码“变得有趣”。这种情况会导致某些界面名称,例如IReadableAndWriteableISomethingAndSomethingAndAnotherThing

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

如果你有权更改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);
}

当然,现在只使用泛型。