35

I was trying to use lombok for my project.

I have a class A:

@Data
@Builder
public class A {
    Integer a1;
}

and a class B:

@Data
public class B extends A {
    Integer b1;

    @Builder
    public B(Integer b1, Integer a1) {
        super(a1);
        this.b1 = b1;
    }
}

I am getting an error saying builder() in B cannot override builder() in A, as return type in BBuilder is not compatible with return type in ABuilder.

Is there some way to do this using lombok? I do not want to write the complete builder for for B, unless I don't have any other option.

PS: I have given explicit constructor for class B due to Issue. I tried searching, but I could not find a good solution for the same.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Abhinav Aggarwal
  • 1,205
  • 2
  • 11
  • 24

5 Answers5

26

Here we just need to call super of the builder.

@Data
public class B extends A {
    Integer b1;

    @Builder
    public B(Integer b1, Integer a1) {
        super(a1);
        this.b1 = b1;
    }

    public static class BBuilder extends ABuilder{
            BBuilder() {
                super();
            }
    }
}
Abhinav Aggarwal
  • 1,205
  • 2
  • 11
  • 24
13

Both child and parent should be marked with @SuperBuilder.

Having both parent and child as @Builder won't work.

Parent class A:

@Data
@SuperBuilder
public class A {
    Integer a1;
}

Child class B:

@Data
@SuperBuilder
public class B extends A {
    Integer b1;
}
walv
  • 2,680
  • 3
  • 31
  • 36
11

Lombok has introduced experimental features with version: 1.18.2 for inheritance issues faced with Builder annotation, and can be resolved with @SuperBuilder annotation

Please use lombok version: 1.18.2, @SuperBuilder annotations in child/parent class

Amit Kaneria
  • 5,466
  • 2
  • 35
  • 38
11

If you are using Lombok 1.18.4 along with IntelliJ, following code shall work for you:

@Data
@Builder
class A {
    Integer a1;
}

@Data
class B extends A {
    Integer b1;

    @Builder (builderMethodName = "BBuilder")
    public B(Integer b1, Integer a1) {
        super(a1);
        this.b1 = b1;
    }
}

public class Main {

    public static void main(String[] args){
    System.out.println(B.BBuilder().a1(1).b1(1).build());

    }
}

One a side note, @SuperBuilder annotation didn't work in IntelliJ at time of writing this answer. If you have multiple level of inheritance, please avoid Lombok or it will make your Java models messy.

realPK
  • 2,630
  • 29
  • 22
2

After hours of hacking at this, I found a viable solution without using the @SuperBuilder. Consider an example -

public class A{
    int x;
    
    @Builder(toBuilder = true)
    public A(int x){
        this.x = x;
    }
    
    public static class ABuilder{
        protected ABuilder(){} //Note this is important, otherwise BBuilder won't be able to access private no-args constructor of ABuilder
    }
}

public class B extends A{
    
    @Builder(builderMethodName="BBuilder", toBuilder=true)
    public B(int x){
        super(x);
    }
    
    public static class BBuilder extends ABuilder{
        BBuilder(){
            super();
        }
    }
}

public static void main(){
    B obj = new B();
    //we can use the existing obj as  obj.toBuilder().x(5).build();
    //this will return an object of B and not A

}

P.S : I am not sure if @SuperBuilder is an experimental feature still ; so didn't want to take chances