Reputation: 8847
I have
public class First<T> {}
public class Second<T extends SomeConcreteClass> extends First<T> {}
public class Third<T> extends Second<T> {} //Compile-time error
I get the compile-time error
Type argument T is not with bounds of type-variable T.
When I contruct a Third
, I want to be able to give the generic parameter as SomeConcreteClass
(or derived class thereof), and for a run-time error to be thrown if I've offered up a type that is not part of SomeConcreteClass
's inheritance hierarchy.
I would think that the specification in Second
's declaration would simply propagate downward, i.e. it should be implicit in the declaration (and any instantiations) of Third
.
What's with the error?
Upvotes: 20
Views: 22372
Reputation: 297
In our case you can probably replace this:
public class Third<T> extends Second<T> {}
with this:
public class Third extends Second<SomeConcreteClass> {}
To use the T within the constructor and otherwise within the code such as a member field of type T, then you can do like this:
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>
That works. The important thing is the generic on the concrete classes had to specify the actual concrete fragment class in order for the other code in the VB class to access its methods.
Upvotes: 2
Reputation: 37435
You have a downward propagation of the boundary restriction.
If you'd put your code above in generic terms, you will clearly see the restricted declaration. Also, any further inheritance would also need to preserve or further narrow down that restriction. eg :
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> {}
Note that it is now clear that you cannot have
public class Third<T> extends Second<T> {}
As you are missing the required T2
type information for Second<V,T2>
.
When you use a concrete class, this restriction becomes implicit.
Upvotes: 1
Reputation: 4421
public class Third<T> extends Second<T> {}
This is a bound mismatch. You can't extend Second with a generic T when you have just specified that second is of type T than extends SomeConcreteClass. When you extend Second, you need to do so with something that is within the scope of SomeConcreteClass.
public class Third<T> extends Second<ClassThatExtendsSomeConcreteClass> {}
or just
public class Third<T> extends Second<SomeConcreteClass> {}
Upvotes: 0
Reputation: 198033
All you need is
public class Third<T extends SomeConcreteClass> extends Second<T>
You just need to respecify the bound. It doesn't propagate like you think it does.
(I'm not positive of the reason for this, but I have some guesses -- what if it was Third<T> extends Second<Foo<T>>
? The appropriate bound on T
isn't obvious, if there even is one. So instead, it just doesn't propagate automatically; you have to specify it.)
Upvotes: 24