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>
Stefan
  • 838
  • 3
  • 13
  • 28
  • 2
    [This answer](http://stackoverflow.com/questions/7354740/is-there-a-way-to-refer-to-the-current-type-with-a-type-variable/7355094#7355094) 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. – Paul Bellora Oct 31 '11 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. – Stefan Oct 31 '11 at 21:03
  • 2
    @Stefan Agreed, totally valid question. Upvoted to counter. – G_H Oct 31 '11 at 21:07
  • 1
    The answer linked actually helped me solve the problem. Change Foo declaration to: public abstract class AbstractFoo>. Create final class ConcreteFoo extends AbstractFoo without extra functionality. It does however destroy some of the inheritance. – Stefan Oct 31 '11 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. – Stephan Oct 31 '11 at 21:11
  • @Stephan I agree. At this point im trying to see how far i can take the language. Especially since i like the idea of fluent interfaces in combination with the Builder pattern. – Stefan Oct 31 '11 at 21:21
  • @Stefan - Glad my linked answer helped, seems it was more relevant than I thought. I used the fluent/builder combination for a home-rolled query builder API, and this little trick was the key to supporting a call like `RedQueryBuilder = new RedQueryBuilder().baseMethod().redMethod();`. It's just important to realize that it isn't suited to be publicly extendable since there's nothing forcing an extending class to follow the rules. For example, one can declare `class EvilQueryBuilder extends QueryBuilder`. – Paul Bellora Oct 31 '11 at 22:00
  • @Kublai Khan coincidentally im using it for a personal 'query builder API' ;) – Stefan Oct 31 '11 at 22:06

1 Answers1

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.

Mark Peters
  • 80,126
  • 17
  • 159
  • 190
  • I guess the problem stems from the fact that Foo doesnt extend itself. – Stefan Oct 31 '11 at 21:23
  • 1
    @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`. Just like `List` doesn't extend `List`, but some subclass could. – Mark Peters Oct 31 '11 at 21:26
  • 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](http://stackoverflow.com/questions/7354740/is-there-a-way-to-refer-to-the-current-type-with-a-type-variable/7355094#7355094) in order to get working fluent interfaces with inheritance structure. – Stefan Nov 03 '11 at 15:15