-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Builder should support fields from parent classes #853
Comments
👤 elreydetodo 🕗 May 29, 2015 at 21:54 UTC In a project I'm working on, I have an abstract base class with three sub-classes. Let's say that the base class has "id", "name", and "type" fields. I would expect one of the subclasses annotated with @ Builder to be able to set those fields in its builder implementation. On a related note (though probably warranting a separate bug), @ AllArgsConstructor should probably take fields from parent classes into account. I think it would be reasonable for this to be an option I have to pass to the annotation (i.e. @ Builder(includeFromParent=true)). |
👤 Maaartinus 🕗 May 30, 2015 at 07:15 UTC For Builder, see For why it's not implemented yet, see Related problem |
End of migration |
Would be nice to include the workaround in the official documentation (on @builder) @AllArgsConstructor
public class Parent {
private String a;
}
public class Child extends Parent {
private String b;
@Builder
public Child(String a, String b){
super(a);
this.b = b;
}
}
public static void main(String[] ...){
Child.builder().a("testA").b("testB").build();
} |
Builder pattern that supports inheritance without the chicken and egg problem - not the cleanest code, cluttered with generics, but since this is to be generated, maybe worth considering? public class Parent {
private final int a;
protected Parent(final AbstractParentBuilder builder) {
this.a = builder.a;
}
public static final class Builder extends AbstractParentBuilder<Parent, Builder> {
public Parent build() {
return new Parent(this);
}
}
protected static abstract class AbstractParentBuilder<T extends Parent, B extends AbstractParentBuilder<T, ?>> {
private int a;
public B withA(int a) {
this.a = a;
return (B) this;
}
}
}
public class Child extends Parent {
private final int b;
protected Child(final AbstractChildBuilder builder) {
super(builder);
this.b = builder.b;
}
public static final class Builder extends AbstractChildBuilder<Child, Builder> {
public Child build() {
return new Child(this);
}
}
protected static abstract class AbstractChildBuilder<T extends Child, B extends AbstractChildBuilder<T, ?>> extends Parent.AbstractParentBuilder<T, B> {
private int b;
public B withB(int b) {
this.b = b;
return (B) this;
}
}
} With that, code below is valid:
We may get rid of casts, adding some abstract self() method, implemented in concrete Builders. |
I came here from peichhorn/lombok-pg#78, which has a ton of +1s. I hope the maintainers here are aware of this. |
+1 |
9 similar comments
+1 |
+1 |
+1 |
+1 |
+1 |
+1 |
+1 |
+1 |
+1 |
|
@rspilker there is a lot of other upvotes for this, but people made those in the wrong repo: peichhorn/lombok-pg#78 (comment) |
+1 |
7 similar comments
+1 |
+1 |
+1 |
+1 |
+1 |
+1 |
+1 |
+1. |
@driverpt Thanks for the workaround. But you have to generate the constructor for all fields, which can be huge for some entity classes! Too bad the @AllArgConstructor doesn't support inheritance either. 😝 |
+1 |
+1 |
This issue cannot be fixed without major changes to Lombok, i.e., deferring Lombok processing to after the sematic analysis of the compiler. Thus, we have investigated on workarounds to this problem. This is the solution we came up with. Let's assume we have two classes: a superclass Superclass:
Subclass:
How to use:
Remarks:
We implemented this for the Eclipse builder, and it works quite well. :-) |
You can invert Builder pattern and take builder instance as the param of constructor, this way Builder can be easily inherited, with added params in child class. So you could add class A {
final int x;
A(Builder b) {
this.x = b.x;
}
static class Builder {
public int x;
A build() {
return new A(this);
}
}
}
class B extends A {
final int y;
B(Builder b) {
super(b);
this.y = b.y;
}
static class Builder extends A.Builder {
public int y;
@Override B build() {
return new B(this);
}
}
} I removed setters on builder for brevity; |
+1 |
2 similar comments
+1 |
+1 |
Can you guys stop posting these useless +1 at the bottom, wasting both your and everyone else's time who have subscribed to this page. If you want the issue to get more attention, post a thumbs up for the first post, not at the bottom |
I created a pull-request (#1337, hehe) that addresses this issue. I followed the idea of @Krzychek mentioned before: Generate a constructor on the type that takes a builder as a parameter and uses the fields from the builder to set the fields of the new instance. The The feature only works for type builders and must be explicitly switched on, in order to not break existing implementations, which may rely on the all-args constructor generated by Example:
|
It would be great to get some feedback from the project developers. If my PR has a chance of getting included, I'll fix the current conflicts in the PR to make it mergeable again, and/or improve the code if you have any remarks. |
@rzwitserloot Any response to the above query? |
+1 |
1 similar comment
+1 |
Well the workaround(s) provided so far are not that useful nor great. Here is an example: |
Agreed. There are still no ideal workarounds. |
Please stop submitting +1 to the request - it only results in unnecessary comments and pollutes the post. If you agree/disagree please use proper comment/reaction/emoji above. |
Still no progress in this issue? |
+1 |
+2 ;) |
+1 |
I see a lot of +1s, but is this issue fixed? |
…ok/lombok#853 and projectlombok/lombok#1337) to ensure fluent usage patterns illustrated in GrafanaClientDashboardIntegrationTest continue to work
@sumeettakalkar Issue is still open. #1337 having good discussion & solutions. I am not seeing any clean solution. May be I need to use lombok without builder pattern as I my project is using heavy use of inheritance. Previously I thought it would be easy or may be I can create some hack around @builder. Any way it is worth to watch #1337 @janrieke Thanks for PR. |
+1 please support this |
There is a new PR coming with a modified approach, as my first approach still required casting, which simply doesn't look good. |
New pull request #1711 with an improved approach. |
Seems like #1711 is released as experimental in version 1.18.2, so this issue may be closed? |
Migrated from Google Code (issue 818)
The text was updated successfully, but these errors were encountered: