代码之家  ›  专栏  ›  技术社区  ›  Andrei Fierbinteanu

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

  •  30
  • Andrei Fierbinteanu  · 技术社区  · 16 年前

    假设我有这些接口:

    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有不同的继承树,这并不是一个真正的选择去做类似于独居和不拥有共同父母的事情。

    我知道你可以做到:

    public void method(I1 param) {
      param.foo();
      ((I2)param).bar();
    }
    

    但是你也可以打电话 method(new C()) 它不能实现I2,所以你会遇到麻烦。

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

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

    4 回复  |  直到 10 年前
        1
  •  22
  •   Sripathi Krishnan    16 年前

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

    这也许是唯一的办法。

        2
  •  9
  •   hqt    10 年前

    我认为从设计的角度来看,上述答案并不好。在创建接口时,要确保调用方对象具有 责任 对于该接口中定义的某些操作。所以有两个解决方案在上面讨论,我会告诉你为什么这些解决方案在设计上不好。

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

    希望有帮助:)

        3
  •  2
  •   Braincompiler    16 年前

    在Java 1.5之前,IMO没有解决方案来在编译时实现这种类型的安全性。但是在运行时有一个使用“instanceof”的soultion。

    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 ...
    }
    
        4
  •  2
  •   Community Mohan Dere    9 年前

    sri 如果您有权更改A和B的签名,则是最佳答案。但是,如果您没有权限,则可以执行以下操作:

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

    当然,现在只使用泛型。