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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3108182/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 16:30:54  来源:igfitidea点击:

Using parameter that implements multiple interfaces pre-generics

javagenericsparametersmultiple-inheritance

提问by Andrei Fierbinteanu

Suppose I have these interfaces:

假设我有这些接口:

public interface I1 {
  void foo();
}

public interface I2 {
  void bar();
}

and the classes:

和课程:

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
}

Now, with generics I can have a method like:

现在,使用泛型,我可以使用如下方法:

public <T extends I1 & I2> void method(T param) {
  param.foo();
  param.bar();
}

and I can call it with both A and B as parameters, but not with C (it doesn't implement I2).

我可以使用 A 和 B 作为参数调用它,但不能使用 C(它没有实现 I2)。

Was there a way of achieving this type of type safety pre generics (java < 1.5).

有没有办法实现这种类型安全的预泛型(java < 1.5)。

Consider that A, B and C have different inheritance trees, and it's not really an option to do something like AParent and BParent having a common parent themselves.

考虑到 A、B 和 C 具有不同的继承树,并且执行类似 AParent 和 BParent 本身具有共同父级的操作并不是一个真正的选择。

I know you could do:

我知道你可以这样做:

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

but then you could also call method(new C())which doesn't implement I2, so you get into trouble.

但是你也可以调用method(new C())which 没有实现 I2,所以你会遇到麻烦。

So are there any other ways you could have done this?

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

P.S. : I don't really need to do this, it's mostly out of curiosity that I ask.

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

采纳答案by Sripathi Krishnan

Create a third interface I3 extends I1 and I2. Then class A and B both implement I3, and the generic method accepts I3.

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

That's perhaps the only way to do it.

这也许是唯一的方法。

回答by BraincompilerLC

Before Java 1.5 there is IMO no solution to achieve such type-sefety at compile-time. But there is a soultion at runtime using "instanceof".

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

回答by emory

sriis the best answer if you had permission to change the signature of A and B. However, if you did not have permission, then you could have done:

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

Of course, now just use generics.

当然,现在只使用泛型。

回答by hqt

I don't think above answers are good under design viewpoint. When you make an interface, you want to make sure caller object has responsibilityfor some actions defined in that interface. So there are two solutions discussing above, and I will tell why those solutions aren't good in design viewpoint.

我不认为以上答案在设计观点下是好的。当您创建一个接口时,您希望确保调用者对象负责该接口中定义的某些操作。所以上面讨论了两种解决方案,我将说明为什么这些解决方案在设计观点上并不好。

1. make one interface extends both two interfaces:

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

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

Above code is non-sense. You define a separate interface just to combine other interfaces, and inside there aren't any new methods. You add no value to ICinstead of combine two interface IAand IB. And some situations, this way will make your code "little fun" when you cannot find the suitable name for third interface. This situation will lead to some interface name such as IReadableAndWriteableor ISomethingAndSomethingAndAnotherThing

上面的代码是没有意义的。你定义一个单独的接口只是为了组合其他接口,里面没有任何新的方法。您不添加任何值,IC而不是将两个接口IAIB. 并且在某些情况下,当您找不到适合第三个接口的名称时,这种方式会使您的代码“有点有趣”。这种情况会导致一些接口名称如IReadableAndWriteableISomethingAndSomethingAndAnotherThing

2. type cast inside method:

2. type cast inside 方法:

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

This way is nonsense too. Why the input parameter is IAthen you must execute some action from interface IB? Under programmer viewpoint, there is no way to know that except from reading your document. That's not good for designing a function for other people use.

这种方式也是废话。为什么输入参数是IA那么你必须从界面执行一些操作IB?在程序员的观点下,除了阅读您的文档之外,没有办法知道这一点。这不利于设计供其他人使用的功能。

True solution:

真正的解决方案:

Above solutions there is another problem in design: You forceprogrammer use one object that has responsibility for two interfaces. What is the problem if programmer doesn't want to do this. They want to use two different concreted class for each different interfaces for easier testing, clean code? They cannot.

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

You should make two different parameters in your method signature:

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

public void exampleMethod(IA object1, IB object2) {
   object1.someMethod()
   object2.someMethod()
}

And for calling above method, you put same parameter inside(if programmer use same object). They also can put different objects too.

对于调用上述方法,您将相同的参数放入其中(如果程序员使用相同的对象)。他们也可以放置不同的物体。

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

Hope this help :)

希望这有帮助:)