9

I am using a fluent interface with inheritance. I declared the base class Constructor protected so you cant create a Foo<Bar> which would result in a ClassCastException on calling add(). But i am having trouble with the static method that returns a new Foo instance.

public class Foo<T extends Foo<T>> // if i change to extends Foo i only get warnings { public static Foo<Foo> createFoo() // <-- error { return new Foo<Foo>(); // <-- error } protected Foo() {} public T add() { //... return (T)this; } } public class Bar extends Foo<Bar> { public Bar sub() { //... return this; } } 

This is mostly an excercise(personal not homework) in Fluent Interfaces, Domain-specific language and Generics, so please dont ask what i need it for.

Edit: Eclipse error

Bound mismatch: The type Foo is not a valid substitute for the bounded parameter <T extends Foo<T>> of the type Foo<T> 
8
  • 2
    This answer should help explain the meaning of the error you're seeing (after the bold EDIT specifically). In the future please post the complete error message in your question. Commented Oct 31, 2011 at 20:46
  • I dont know what the downvote is for, i searched for selfbound generic types on google and could not find an answer to my problem. Commented Oct 31, 2011 at 21:03
  • 2
    @Stefan Agreed, totally valid question. Upvoted to counter. Commented Oct 31, 2011 at 21:07
  • 1
    The answer linked actually helped me solve the problem. Change Foo declaration to: public abstract class AbstractFoo<T extends AbstractFoo<T>>. Create final class ConcreteFoo extends AbstractFoo<ConcreteFoo> without extra functionality. It does however destroy some of the inheritance. Commented Oct 31, 2011 at 21:10
  • Generics can really be a pain if you "misuse" (no offense) them like this. I am really a friend of them, but sometimes they make it much harder to write code as without them. Try to declare different types instead of a recursive structure, which is hard to maintain and extend. Commented Oct 31, 2011 at 21:11

1 Answer 1

3

You essentially have a recursive type declaration.

Foo<T extends Foo<T>>.

So let's say you have a Foo<Foo>. That means T is mapped to Foo. But Foo is not subtype of Foo<T>, which in this case is Foo<Foo>, so what you're really looking for is Foo<Foo<Foo>>. But wait a minute, the innermost Foo isn't typed, so I guess it's Foo<Foo<Foo<Foo>>>...oh forget it!

To put a more understandable face on it, consider if you had Foo<T extends List<T>>. What could you possibly use for T in a declaration/instantiation of Foo? List<String>? List<List>?

Edit

It looks like you found a way to "break" the recursion cycle. You eventually need to get to a reified type. In the same way that you found that ConcreteFoo worked for you, you could similarly for the List example above have some class ConreteListOfItself implements List<ConreteListOfItself> that would break the recursion cycle.

Sign up to request clarification or add additional context in comments.

3 Comments

I guess the problem stems from the fact that Foo doesnt extend itself.
@Stefan: Well, extends in the context of a type bound means a subclass or the class itself. So the problem isn't that Foo doesn't extend Foo, the problem is that Foo doesn't extend Foo<Foo>. Just like List doesn't extend List<List>, but some subclass could.
I am going to accept this answer, as it explains why what im trying to do 'doesnt' work. At this point i think i need a more powerful Generics mechanism in line of what Kublai Khan says here in order to get working fluent interfaces with inheritance structure.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.