Hallo, ich bin ein Neuling in der Kotlin-Welt. Mir gefällt, was ich bisher gesehen habe, und ich habe darüber nachgedacht, einige unserer Bibliotheken, die wir in unserer Anwendung verwenden, von Java nach Kotlin zu konvertieren.
Diese Bibliotheken sind voll von Pojos mit Setter-, Getter- und Builder-Klassen. Jetzt habe ich gegoogelt, um herauszufinden, wie Builder in Kotlin am besten implementiert werden können, aber ohne Erfolg.
2. Update: Die Frage ist, wie man ein Builder-Entwurfsmuster für ein einfaches Pojo mit einigen Parametern in Kotlin schreibt. Der folgende Code ist mein Versuch, Java-Code zu schreiben und dann das Eclipse-Kotlin-Plugin zu verwenden, um nach Kotlin zu konvertieren.
class Car private constructor(builder:Car.Builder) {
var model:String? = null
var year:Int = 0
init {
this.model = builder.model
this.year = builder.year
}
companion object Builder {
var model:String? = null
private set
var year:Int = 0
private set
fun model(model:String):Builder {
this.model = model
return this
}
fun year(year:Int):Builder {
this.year = year
return this
}
fun build():Car {
val car = Car(this)
return car
}
}
}
design-patterns
kotlin
Keyhan
quelle
quelle
model
undyear
um veränderlich zu sein? Ändern Sie sie nach einerCar
Kreation?Antworten:
In erster Linie müssen Sie in Kotlin in den meisten Fällen keine Builder verwenden, da wir Standardargumente und benannte Argumente haben. Dadurch können Sie schreiben
und benutze es so:
Wenn Sie unbedingt Builder verwenden möchten, gehen Sie wie folgt vor:
Den Builder zu einem zu machen,
companion object
macht keinen Sinn, weilobject
s Singletons sind. Deklarieren Sie es stattdessen als verschachtelte Klasse (die in Kotlin standardmäßig statisch ist).Verschieben Sie die Eigenschaften in den Konstruktor, damit das Objekt auch auf normale Weise instanziiert werden kann (machen Sie den Konstruktor privat, falls dies nicht der Fall sein sollte), und verwenden Sie einen sekundären Konstruktor, der einen Builder übernimmt und an den primären Konstruktor delegiert. Der Code sieht wie folgt aus:
Verwendung:
val car = Car.Builder().model("X").build()
Dieser Code kann mithilfe eines Builder-DSL zusätzlich gekürzt werden :
Verwendung:
val car = Car.build { model = "X" }
Wenn einige Werte erforderlich sind und keine Standardwerte haben, müssen Sie sie in den Konstruktor des Builders und auch in die
build
gerade definierte Methode einfügen:Verwendung:
val car = Car.build(required = "requiredValue") { model = "X" }
quelle
Car.Builder builder = new Car.Builder();
. Allerdings verfügt nur die erste Version über eine flüssige Oberfläche, sodass die Aufrufe der zweiten und dritten Version nicht verkettet werden können.Ein Ansatz besteht darin, Folgendes zu tun:
Anwendungsbeispiel:
quelle
Da ich die Jackson-Bibliothek zum Parsen von Objekten aus JSON verwende, benötige ich einen leeren Konstruktor und kann keine optionalen Felder haben. Auch müssen alle Felder veränderbar sein. Dann kann ich diese nette Syntax verwenden, die dasselbe tut wie das Builder-Muster:
quelle
@JsonProperty
@JsonProperty
, wenn Sie mit dem-parameters
Switch kompilieren .Ich persönlich habe noch nie einen Baumeister in Kotlin gesehen, aber vielleicht bin es nur ich.
Alle Validierungen, die benötigt werden, erfolgen im
init
Block:Hier habe ich mir erlaubt zu erraten, dass du nicht wirklich wolltest
model
undyear
veränderlich sein willst . Auch diese Standardwerte scheinen keinen Sinn zu haben (besondersnull
fürname
), aber ich habe einen zu Demonstrationszwecken hinterlassen.Eine Meinung: Das Builder-Muster, das in Java verwendet wird, um ohne benannte Parameter zu leben. In Sprachen mit benannten Parametern (wie Kotlin oder Python) empfiehlt es sich, Konstruktoren mit langen Listen von (möglicherweise optionalen) Parametern zu haben.
quelle
@JvmOverloads
kotlinlang.org/docs/reference/…Ich habe viele Beispiele gesehen, die als Bauherren zusätzlichen Spaß erklären. Ich persönlich mag diesen Ansatz. Sparen Sie Aufwand beim Schreiben von Buildern.
Ich habe noch keinen Weg gefunden, der die Initialisierung einiger Felder in DSL erzwingen kann, z. B. das Anzeigen von Fehlern, anstatt Ausnahmen auszulösen. Lassen Sie mich wissen, wenn jemand weiß.
quelle
Für eine einfache Klasse benötigen Sie keinen separaten Builder. Sie können optionale Konstruktorargumente verwenden, wie von Kirill Rakhman beschrieben.
Wenn Sie eine komplexere Klasse haben, bietet Kotlin eine Möglichkeit, Builder / DSL im Groovy-Stil zu erstellen:
Typensichere Builder
Hier ist ein Beispiel:
Github-Beispiel - Builder / Assembler
quelle
Menschen nowdays sollte Kotlin Check Typ-Safe - Builders .
Die Verwendung dieser Art der Objekterstellung sieht ungefähr so aus:
Ein schönes Anwendungsbeispiel in Aktion ist das Vaadin-on-Kotlin- Framework, das typsichere Builder zum Zusammenstellen von Ansichten und Komponenten verwendet .
quelle
Ich bin zu spät zur Party. Das gleiche Dilemma hatte ich auch, wenn ich im Projekt das Builder-Muster verwenden musste. Später, nach Recherchen, habe ich festgestellt, dass dies absolut unnötig ist, da Kotlin bereits die genannten Argumente und Standardargumente bereitstellt.
Wenn Sie wirklich implementieren müssen, ist Kirill Rakhmans Antwort eine solide Antwort darauf, wie Sie am effektivsten implementieren können. Eine andere Sache, die Sie vielleicht nützlich finden, ist https://www.baeldung.com/kotlin-builder-pattern, die Sie bei ihrer Implementierung mit Java und Kotlin vergleichen und gegenüberstellen können
quelle
Ich würde sagen, dass das Muster und die Implementierung in Kotlin ziemlich gleich bleiben. Sie können es manchmal dank Standardwerten überspringen, aber für eine kompliziertere Objekterstellung sind Builder immer noch ein nützliches Werkzeug, das nicht weggelassen werden kann.
quelle
Sie können optionale Parameter im Kotlin-Beispiel verwenden:
dann
quelle
quelle
Ich habe ein grundlegendes Builder-Muster in Kotlin mit dem folgenden Code implementiert:
Und schlussendlich
Java:
Kotlin:
quelle
Ich habe an einem Kotlin-Projekt gearbeitet, das eine von Java-Clients verwendete API verfügbar gemacht hat (die die Kotlin-Sprachkonstrukte nicht nutzen kann). Wir mussten Builder hinzufügen, um sie in Java verwendbar zu machen. Deshalb habe ich eine @ Builder-Annotation erstellt: https://github.com/ThinkingLogic/kotlin-builder-annotation - sie ist im Grunde ein Ersatz für die Lombok @ Builder-Annotation für Kotlin.
quelle