Как использовать Lombok @SuperBuilder на абстрактных классах с конечными полями - PullRequest
1 голос
/ 20 февраля 2020

Учитывая следующие классы с аннотациями Lombok @Data и @SuperBuilder

@Data
@SuperBuilder
public abstract class Parent {

    protected final String userId;
    protected final Instant requestingTime;
}

@Data
@SuperBuilder
public class Child extends Parent {

    private final Instant beginningDate;
    private final Instant endingDate;
    private final Collection<String> fields;
}

Я получаю следующую ошибку, появляющуюся над аннотацией @Data в классе Child:

Неявный супер-конструктор Parent () не определен. Должен явно вызывать другой конструктор.

Есть ли способ настроить конструктор не по умолчанию в аннотации Child класса *1014*, чтобы иметь все поля final в обоих Child и Parent классы инициализируются при вызове Builder?

Я пробовал несколько разных комбинаций аннотаций @Data, @Getter, @Setter с аннотацией @SuperBuilder как для дочернего, так и для дочернего элементов. родительские классы, но еще не нашли рабочего решения. Я использую Lombok 1.18.10.

Для справки этот вопрос связан

РЕДАКТИРОВАТЬ

Это фактически тот конструктор, который Ломбок должен создавать и вызывать для операции SuperBuilder.build().

public Child(
    final String userId,
    final Instant requestingTime,
    final Instant beginningDate,
    final Instant endingDate,
    final Collection<String> fields) {

    super(userId, requestingTime);
    this.beginningDate = beginningDate;
    this.endingDate = endingDate;
    this.fields= fields;
}

В соответствии с запросом, я бы ожидал вызвать конструктор для объекта Child.

final Child child = Child.Builder()
                         .userId(<value>)
                         .requestingTime(<value>)
                         .beginningDate(<value>)
                         .endingDate(<value>)
                         .fields(<value>)
                         .build();

Ответы [ 2 ]

2 голосов
/ 20 февраля 2020

AFAIK, @Data генерирует @NoArgsConstructor, что просто неправильно. На самом деле, @Data неверно само по себе, так как оно предназначено для изменяемых классов; @Value было бы лучше, но он не может работать и с супер-конструктором.

Поэтому удалите @Data, добавьте @Getter, @EqualsAndHashCode, @ToString и все, что вам нужно. Не забудьте добавить callSuper=true в подкласс.


Фактически это конструктор, который Lombok должен создавать и вызывать в операции SuperBuilder.build ().

public Child(
    final String userId,
    final Instant requestingTime,
    final Instant beginningDate,
    final Instant endingDate,
    final Collection<String> fields) {

    super(userId, requestingTime);
    this.beginningDate = beginningDate;
    this.endingDate = endingDate;
    this.fields= fields;
}

Нет, SuperBuilder работает не так. Это на самом деле Ломбок не может сделать, так как он не видит супер полей. Вместо этого строитель использует что-то вроде

public Child(ChildBuilder b) {    
    super(b);
    this.beginningDate = b.beginningDate;
    this.endingDate = b.endingDate;
    this.fields= b.fields;
}

Вы можете верить тому, что говорит Ян Рике, он написал это.

0 голосов
/ 20 февраля 2020

@ Аннотация данных неявно генерирует код для следующих функций:


  • setter
  • getter
  • toString
  • equallAndHashCode
  • конструктор (только для обязательных аргументов)

Это означает, что объявление конструктора loombok сгенерирует код для родительского класса, как указано ниже:

Person (String userId, Instant requesttingTime)

Аналогично для дочернего класса:

Child (Мгновенное началоDate, Мгновенное окончаниеDate, Поля коллекции)


Теперь, когда ваша программа выдает исключение,

Parent () не определено в родительском классе.

Пожалуйста, аннотируйте свой класс с помощью:

@ NoArgsConstructor

Это создаст требуемый конструктор по умолчанию.

...