繁体   English   中英

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

[英]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添加任何值,而不是将两个接口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);       
}

希望这有帮助:)

在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM