Lombok'ta süper yapıcı nasıl aranır


118

Sınıfım var

@Value
@NonFinal
public class A {
    int x;
    int y;
}

Başka bir B sınıfım var

@Value
public class B extends A {
    int z;
}

lombok, A () yapıcısını bulamadığını söyleyen bir hata veriyor, bunu açıkça çağırmak istiyorum, lombok'un yapmasını istediğim şey, aşağıdaki kodu oluşturacak şekilde sınıf b'ye açıklama vermektir:

public class B extends A {
    int z;
    public B( int x, int y, int z) {
        super( x , y );
        this.z = z;
    }
}

Bunu Lombok'ta yapmak için bir açıklamamız var mı?

Yanıtlar:


169

Lombok'ta bu mümkün değil. Gerçekten güzel bir özellik olsa da, süper sınıfın kurucularını bulmak için çözüm gerekiyor. Süper sınıf, Lombok'un çağrıldığı anda yalnızca adıyla bilinir. Gerçek sınıfı bulmak için içe aktarma deyimlerini ve sınıf yolunu kullanmak önemsiz değildir. Ve derleme sırasında, yapıcıların bir listesini almak için yansımayı kullanamazsınız.

Bu tamamen imkansız değildir ama çözünürlük kullanılarak sonuçları valve @ExtensionMethodolduğunu bize öğretti zor ve hata eğilimli.

Açıklama: Ben bir Lombok geliştiricisiyim.


@ roel-spilker Arkasındaki karmaşıklıkları anlıyoruz. Ancak Lombok , oluşturulan kurucuya Lombok'un inConstructorhangi yapıcısını superenjekte edeceğini belirleyebileceğimiz yapıcı ek açıklamaları için bir yöntem sağlayabilir mi?
Manu Manjunath

1
afterConstructor'ın bazı otomatik başlatma işlemleri yapması da iyi olurdu
Pawel

@ Manu / @ Pawel: lombok geliştirme isteğine bakın: github.com/peichhorn/lombok-pg/issues/78 (şu anda açık)
JJ Zabkar

@Builder resmi sürümde olduğu için bkz: github.com/rzwitserloot/lombok/issues/853
Sebastian

4
Hala mümkün değil mi?
FearX

21

Lombok Sayı # 78 bu sayfaya atıfta bulunur https://www.donneo.de/2015/09/16/lomboks-builder-annotation-and-inheritance/ bu güzel açıklama ile:

@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;   
  } 
} 

Sonuç olarak, oluşturulan oluşturucuyu şu şekilde kullanabilirsiniz:

Child.builder().a("testA").b("testB").build(); 

Resmi belgeler bu açıklar, ancak açıkça bu şekilde bunu kolaylaştırabilir işaret etmez.

Ayrıca bunun Spring Data JPA ile iyi çalıştığını buldum.


Spring Data JPA ile kullanılmasının bir örneğini verebilir misiniz?
Marc Zampetti

30
Bu soruya hiç cevap vermiyor. Bunun yerine işi elle yapıyor, soru ise nasıl üretileceğiydi. Aynı zamanda soruyla ilgisi olmayan @ Builder'ı sürükleyerek her şeyi daha kafa karıştırıcı hale getiriyor.
Jasper

8
Aslında bu, sadece bir kalıtım yapısı oluşturmak ve ardından oluşturucu kullanmak isteyenler için çok kullanışlıdır. Zaten #lombok kullanmamın% 99 nedeni bu. Bazen istediğimiz şekilde çalışmasını sağlamak için el işçiliği yapmamız gerekir. Çok teşekkürler @ jj-zabkar
Babajide Prince

ama sonra; basitçe self + parent arg yapıcısını kodlayın. İnşaatçı kullanmaya gerek yok
Juh_

STS ve tutulmada çalışacak, ancak uygulamanızın JAR dosyasını oluşturduğunuzda büyük olasılıkla başarısız olacaktır. Hem SuperBuilder, Builder'ı kalıtım için denedim. İkisi de başarısız oldu. Dikkatli ol !!
P Satish Patro

6

Lombok, herhangi bir @Valueaçıklamalı sınıf oluşturarak final(kullanarak bildiğiniz gibi) belirtilen bunu desteklemez @NonFinal.

Bulduğum tek çözüm, tüm üyeleri kendiniz nihai ilan etmek ve @Databunun yerine ek açıklamayı kullanmaktır. @EqualsAndHashCodeLombok süper sınıflardan birini tüm bağımsız değişkenleri kullanarak nasıl oluşturacağını bilmediğinden, bu alt sınıflar tarafından açıklanmalı ve açık bir tüm bağımsız değişken oluşturucuya ihtiyaç duyulmaktadır:

@Data
public class A {
    private final int x;
    private final int y;
}

@Data
@EqualsAndHashCode(callSuper = true)
public class B extends A {
    private final int z;

    public B(int x, int y, int z) {
        super(x, y);
        this.z = z;
    }
}

Özellikle alt sınıfların kurucuları, birçok üyesi olan üst sınıflar için çözümü biraz dağınık hale getiriyor, üzgünüm.


1
Neden "alt sınıflara açıklama eklenmesi gerektiğini" biraz daha açıklayabilir misiniz @EqualsAndHashCode? Bu ek açıklama tarafından dahil edilmiyor @Datamu? Thx :)
Gerard Bosch

1
@GerardB @Dataayrıca equals () ve hashCode () oluşturur ancak herhangi bir kalıtımla ilgilenmez. Üst sınıfın eşittir () ve hashCode () kullanıldığından emin olmak için, callSuper
Arne Burmeister

5

birçok üyesi olan üst sınıflar için @ Delegate kullanmanızı öneririm

@Data
public class A {
    @Delegate public class AInner{
        private final int x;
        private final int y;
    }
}

@Data
@EqualsAndHashCode(callSuper = true)
public class B extends A {
    private final int z;

    public B(A.AInner a, int z) {
        super(a);
        this.z = z;
    }
}

Bu, onun gibi ilginç bir yaklaşım!
Arne Burmeister

@Delegateolduğunu @Target({ElementType.FIELD, ElementType.METHOD}). AInner alan olmalıdır A.
boriselec

3

Çocuk sınıfının ebeveynden daha fazla üyesi varsa, çok temiz değil, kısa yoldan yapılabilir:

@Data
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class User extends BaseEntity {
    private @NonNull String fullName;
    private @NonNull String email;
    ... 

    public User(Integer id, String fullName, String email, ....) {
        this(fullName, email, ....);
        this.id = id;
    }
}

@Data
@AllArgsConstructor
abstract public class BaseEntity {
   protected Integer id;

   public boolean isNew() {
      return id == null;
   }
}


0

Bir seçenek com.fasterxml.jackson.databind.ObjectMapperolarak ebeveynden bir alt sınıfı başlatmak için kullanabilirsiniz .

public class A {
    int x;
    int y;
}

public class B extends A {
    int z;
}

ObjectMapper MAPPER = new ObjectMapper(); //it's configurable
MAPPER.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false );
MAPPER.configure( SerializationFeature.FAIL_ON_EMPTY_BEANS, false );

//Then wherever you need to initialize child from parent:
A parent = new A(x, y);
B child = MAPPER.convertValue( parent, B.class);
child.setZ(z);

lombokİhtiyaç duyarsanız , yine de A ve B üzerindeki ek açıklamaları kullanabilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.