如何参数化使用通配符参数扩展类型的类型?

时间:2010-03-01 13:25:52

标签: java generics

我有一个参数化的接口,它扩展了参数化类型,该接口包含一个需要扩展类型的类型参数的方法。在代码中,这就是我想要的:

class Thingy<X> { ... }

interface Foo<P extends Thingy<?>> {
  <T> T frobnicate(P<T> a);
}

但那不编译。为了正确frobnicate Thingy,有必要知道Thingy的类型,但也有些Foo可能专门用于处理特定种类的Thingy {1}} s(例外情况是它们必须能够处理任何类型T任何Thingy被参数化。)

(顺便说一句,我已经发现了these questions。前者只需要一个通用参数;我不在乎这里是否需要一个,两个或五个,这么久因为有一些解决方案。后者在我的Foo对应的类中有一个特定的类型而不是通配符,所以这里的解决方案在我看来并不适用。)

修改

由于我想要的Thingy子类的数量很少,我可以通过继承Thingy并创建另一个接口来获得相同的效果:

interface Foo {
  <T> T frobnicate(Thingy<T> a);
}

class SpecialThingy<T> extends Thingy<T> { ... }

interface Bar {
   <T> T frobnicate(SpecialThingy<T> a);
}

这并不像我希望的那样优雅,但它会在这种情况下完成工作。

1 个答案:

答案 0 :(得分:2)

不使用扩展Thingy<T>的类型参数,而是仅使用T的类型参数,并将Thingy部分添加到需要的位置:

class Thingy<X> { }

interface Foo<X> {
  X frobnicate(Thingy<X> a);
}

或者如果您需要使用Thingy的特定子类,那么这个怎么样?

class Thingy<X> { }

interface Foo<X, T extends Thingy<X>> {
  X frobnicate(T a);
}

如果您需要更复杂的东西,那么最简单的方法就是进行运行时类型检查。有时,泛型会产生比它们值得更多的不必要的复杂性。

使用更好的设计也可以避免使用泛型来表达这些东西。为了提出相关的建议,有必要更多地了解Thingies如何使用,并且有一个比Thingies和Foos更具体的例子。

修改

由于要求事先无法知道Thingy的类型参数,因此这应该是唯一的选择:

interface Foo {
  <T> T frobnicate(Thingy<T> a);
}

关注Liskov substitution principle并使其适用于Thingy的所有实施。如果代码只能用于Thingy的某些子类型,那么我认为你不能用泛型来表达它(它需要为类型参数提供类型参数),唯一的选择是运行时类型检查。运行时类型检查是一种代码气味,因此最好修复设计,以便不需要它。