我有一个参数化的接口,它扩展了参数化类型,该接口包含一个需要扩展类型的类型参数的方法。在代码中,这就是我想要的:
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);
}
这并不像我希望的那样优雅,但它会在这种情况下完成工作。
答案 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的某些子类型,那么我认为你不能用泛型来表达它(它需要为类型参数提供类型参数),唯一的选择是运行时类型检查。运行时类型检查是一种代码气味,因此最好修复设计,以便不需要它。