mkarneim / pojobuilder

A Java Code Generator for Pojo Builders
Other
334 stars 44 forks source link

Use recursive generic definition style instead of self pointer to support fluent interface for generation gap #55

Open mkarneim opened 11 years ago

mkarneim commented 11 years ago

Currently PB supports the fluent interface by using a 'self' pointer, which is necessary in the context of the generation gap feature.

This works but has some drawbacks. For example, you can not create a deep inheritance hierarchy of Builder classes by subclassing existing builders.

This can be solved by switching to an alternative approach that copies the recursive generic definition style that Java uses for enums.

See this stackoverflow thread for more information.

drekbour commented 11 years ago

I suddenly find myself wanting to inherit a builder from another builder (since I have a pojo which subclasses another pojo) so am quite keen on this issue!

To make things more interesting I have a generation-gap in between:

mkarneim commented 9 years ago

I just have seen that you are already working in this issue, Marc.

Your implementation does it all fine, but I think you have also spotted the (ugly) side effect: When instantiating a builder we now have to add the generic self-type argument:

Player p = new PlayerBuilder<PlayerBuilder>().withName("Bob").build();

Hmm...

drekbour commented 9 years ago

I'm just playing with it. I'm aware that publicising the generic is very bad and for more than simply cosmetic reasons. It's worse if the pojo has generics too and yet worse that you can 'lie' about the generic token when instantiating the class.

The only solution I see to all of those is to mandate a static factory method to instantiate any builder like this:

public class EventBuilder<B extends EventBuilder<B>, A> {
  public X<A> build() ...
  protected EventBuilder<B,A> () {}
  public static <A> event() { return new EventBuilder<EventBuilder,A>()

without that it is simply not reasonable. Personally, I like the static method anyway as it leads to much more fluent use e.g. emit(event().withName("Default"))

Hence I'm parking my little POC on this issue and will implement the issue on factory methods first

drekbour commented 7 years ago

FYI See #132 which at least allows builder inheritance even if its ugly.