14

I saw some code on an unrelated question but it got me curious as I never saw such construct with Java Generics. What would be the use of creating a generic class that can take as type argument itself or descendants of itself. Here is example :

abstract class A<E extends A<E>> {
    abstract void foo(E x);
}

the first thing that came to mind would be a list that takes a list as parameter. Using this code feels strange, how do you declare a variable of type A ? Recursive declaration !?

Does this even work ? If so did any of you see that in code ? How was it used ?


EDIT

Indeed it turns out my question is the same as this one only phrased differently, but the answers for that question will answer mine as well.

Also thanks for the reference to the Curiously Recurring Template Pattern which gives some historical background and further explanations on the subject.

This old blog entry probably gives the best all around explanation I found for us Java guys.

Now hard to choose a right answer here for they are all helpful, so I will go for the one that ended up yielding the most reading material (referenced above)

Community
  • 1
  • 1
Newtopian
  • 7,543
  • 4
  • 48
  • 71
  • 1
    That should actually read `abstractg class A> {`. Use of `A` requires a generic argument (otherwise it's "raw", and mixing raw and cooked types is a bad idea). The real problem here is that the class is using the naming convention for a generic parameter, which I find incredibly confusing. – Tom Hawtin - tackline Mar 30 '10 at 03:42
  • @ Tom : thanks, yes after reading on the subject and understanding the use of this pattern I realize the error. I have corrected the code above to reflect this. – Newtopian Mar 31 '10 at 01:43

2 Answers2

10

Without this, the parameter to the method foo could not be bound to type E.

If you have an implementation B of this abstract class, you can now enforce that method foo also requires its parameter to be of type B.

 class B extends A<B> {
      void foo (B x){}
 }

Without that, foo would have to take any kind of A.

I agree that the syntax for this is less than elegant.

Thilo
  • 257,207
  • 101
  • 511
  • 656
  • "you can now enforce that method foo also requires its parameter to be of type B." `foo`'s parameter is `B` because `B` is declared to extend `A`. It has nothing to do with the bounds of the type parameter of `A`. – newacct Feb 01 '17 at 01:39
5

Generics aren't just for containers like lists. This sort of "extends itself" type parameter is used to let the superclass refer to the subclass in places like method parameters and return types, even though no actual specific subclass is available when the superclass is compiled. It's analogous to the curiously recurring template pattern in C++.

A subclass of your example would be declared as

class Foo extends A<Foo>

and the inherited foo() method becomes

void foo(Foo x)

See how A defined a method that takes a Foo parameter even though it doesn't actually know about Foo?

Yes, this sort of thing is unusual, but not unheard of: the built-in Enum class uses a similar trick.

Wyzard
  • 33,849
  • 3
  • 67
  • 87
  • "the inherited foo() method becomes `void foo(Foo x)`" only because class `Foo` is declared as `clads Foo extends A`. This is true regardless of the bounds on `E` in `A`. – newacct Feb 01 '17 at 01:38