2015-12-11 13 views
8

Ich habe eine Java AutoValue-Klasse mit einem List-Attribut. Ich möchte zulassen, dass der Builder an die Liste anfügt, anstatt die gesamte erstellte Liste zu übergeben.Ist es möglich, einer Sammlung in Java AutoValue einen Wert hinzuzufügen?

Beispiel:

import com.google.auto.value.AutoValue; 
@AutoValue 
public abstract class Deck { 
    public abstract List<Card> cards(); 
    public static Builder builder() { 
     return new AutoValue_Card.Builder() 
      .cards(new ArrayList<Card>()); 
    } 
    @AutoValue.Builder 
    public abstract static class Builder { 
     public abstract Builder cards(List<Card> cards); 
     /** 
     * Append card to cards in the constructed Deck. 
     */ 
     public Builder addCard(Card card) { 
      // Is it possible to write this function? 
     } 
    } 
} 

Was ist die beste Lösung, um die addCard Funktion für das Schreiben? Unterstützt AutoValue das irgendwie schon? Die Eigenschaft intermediate cards in der konstruierten Klasse ist für den Builder nicht sichtbar, sodass ich nicht direkt darauf zugreifen kann. Ich könnte versuchen, den Builder direkt zu umgehen, indem ich meine eigene Kopie der Karten im Builder aufbewahre, ist das die einzige Option hier?

Antwort

3

Falls jemand es nützlich findet - hier ist der eigentliche Code von dem, was ich vermute Kevin vorgeschlagen. Es war nicht klar, wenn ich zum ersten Mal auf seine Antwort gestolpert, so hier geht:

import com.google.auto.value.AutoValue; 
import com.google.common.collect.ImmutableList; 

@AutoValue 
public abstract class Hand { 
    public static Builder builder() { 
    return new AutoValue_Hand.Builder(); 
    } 

    public abstract Builder toBuilder(); 

    public abstract String name(); 

    public abstract ImmutableList<String> cards(); 

    @AutoValue.Builder 
    public static abstract class Builder { 

    public abstract Builder name(String name); 

    protected abstract ImmutableList.Builder<String> cardsBuilder(); 

    public Builder addCard(String card) { 
     cardsBuilder().add(card); 
     return this; 
    } 

    public abstract Hand build(); 
    } 
} 

Verbrauch:

Hand fullHouseHand = Hand.builder() 
    .name("Full House") 
    .addCard("King") 
    .addCard("King") 
    .addCard("King") 
    .addCard("10") 
    .addCard("10") 
    .build(); 
System.out.print(fullHouseHand); 

Ausgang:

Hand{name=Full House, cards=[King, King, King, 10, 10]} 
7

AutoValue verfügt über einige spezielle Funktionen, die bei der Verwendung von Guavas immutable collections zum Tragen kommen, da diese Sammlungen alle ihre eigenen Builder-Typen haben. (Und natürlich möchten Sie sicher, dass die Eigenschaften Ihrer Wertklassen unveränderlich sind!)

Eine Funktion ist die Definition einer abstrakten cardsBuilder()-Methode, die einen neuen Builder des entsprechenden Sammlertyps startet und an diesen zurückgibt der Anrufer. Das ist super flexibel, aber das Traurige daran ist, dass es "die Kette durchbricht". Der Anrufer ruft nun eine ImmutableList.Builder an und kann nicht mehr auf Deck.Builder zugreifen, um build zu rufen.

Aber Sie können diese Adresse, indem Sie Ihre eigene addCard Methode hinzufügen, wie Sie es oben gezeigt haben, und setzen es nur cardsBuilder().add(card) zu rufen und dann this zurückzukehren anstelle des Erbauers. Problem gelöst!

Ich glaube, das alles sollte in 1.1 funktionieren, aber lass es uns wissen, wenn Sie Probleme haben!

P.S. Ich entschuldige mich - wir haben eine Menge neues Material für das AutoValue-Benutzerhandbuch, einschließlich dieses Themas, das aufgrund einiger technischer Schwierigkeiten bei der Veröffentlichung auf die öffentliche Website geraten ist.

+2

Gibt es Pläne für die gleiche Funktionalität nicht nur für com.google.common.collect Builder, aber für jeden Builder? Ich würde gerne die gleiche Funktionalität für meine generierten Builder verwenden! – oae