使用泛型参数的继承扩展实现多级Java泛型继承

18

我有

public class First<T> {}

public class Second<T extends SomeConcreteClass> extends First<T> {}

public class Third<T> extends Second<T> {} //Compile-time error

我遇到了编译时错误。

Type argument T is not with bounds of type-variable T.

当我构建一个Third时,我希望能够将泛型参数设置为SomeConcreteClass(或其派生类),如果我提供的类型不是SomeConcreteClass的继承层次结构的一部分,则会抛出运行时错误。
我认为在Second的声明中指定应该向下传播,即它应该在Third的声明(和任何实例化)中隐含。
这个错误是什么意思?

如果我提供了一个不是部分的类型,就会抛出运行时错误。我认为你无法理解这个。 "提供类型" 只发生在编译时(然后被擦除)。如果你禁用它(通过不 "提供" 任何类型),你可能会在某个时候得到 ClassCastExceptions,但不是在构造 Third 实例时。 - Thilo
4个回答

23
你所需要的只有

这些

public class Third<T extends SomeConcreteClass> extends Second<T>

您只需要重新指定边界。它不会像您想象的那样自动传播。

我不确定原因,但我有一些猜测 - 如果是 Third<T> extends Second<Foo<T>> 呢?如果甚至有一个适当的边界,那么 T 的适当边界并不明显。所以,它不会自动传播;您需要指定它。


啊,所以没有向下传播。这真是不幸。感谢您的回复。 - Engineer

2
在我们的情况下,您可能可以替换为以下内容:
public class Third<T> extends Second<T> {}

使用以下方法:

public class Third extends Second<SomeConcreteClass> {}

如果你想在构造函数和代码中使用类型为T的成员字段等,那么可以按照以下方式操作:

VB2 extends VB1<Frag2>
...
public VB2(Frag2 frag){...

VB1<T extends Frag1> extends CommonVB<T>
...
public V1(T frag){... /// notice the T

CommonV<T extends CommonFragBase> extends BaseVB<T>
...
public CommonVB(T controller) {...

BaseVB<T extends CommonFragBase>

可以这样做。重要的是,在具体类上指定通用类必须指定实际的具体片段类,以便VB类中的其他代码可以访问其方法。


1
浪费了一个小时在这上面。 - codeslapper

1

您有一个边界限制的向下传播。

如果您将上面的代码以通用术语表示,您将清楚地看到受限声明。此外,任何进一步的继承也需要保留或进一步缩小该限制。例如:

public class First<T> {}

public class Second<U, T1 extends U> extends First<T1> {}

public class Third<V, T2 extends V> extends Second<V,T2> {} 

请注意,现在已经清楚地知道,您无法拥有。
public class Third<T> extends Second<T> {} 

由于您缺少 T2 类型信息,因此无法使用 Second<V,T2>。当您使用具体类时,这个限制变得隐含。


0

public class Third<T> extends Second<T> {}

这是一个绑定不匹配。当您刚刚指定second是类型为T,而且扩展Second时,您不能使用通用T扩展Second。您需要使用在SomeConcreteClass范围内的内容来扩展Second。

public class Third<T> extends Second<ClassThatExtendsSomeConcreteClass> {}

或者只需

public class Third<T> extends Second<SomeConcreteClass> {}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接