Salut, je suis un débutant dans le monde Kotlin. J'aime ce que je vois jusqu'à présent et j'ai commencé à penser à convertir certaines de nos bibliothèques que nous utilisons dans notre application de Java à Kotlin.
Ces bibliothèques regorgent de Pojos avec des setters, des getters et des classes Builder. Maintenant, j'ai cherché sur Google quel est le meilleur moyen d'implémenter Builders dans Kotlin, mais sans succès.
2ème mise à jour: La question est de savoir comment écrire un design-pattern Builder pour un simple pojo avec quelques paramètres dans Kotlin? Le code ci-dessous est ma tentative en écrivant du code java, puis en utilisant le plugin eclipse-kotlin-plugin pour convertir en Kotlin.
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
la source
la source
model
etyear
être mutable? Les changez-vous après uneCar
création?Réponses:
Tout d'abord, dans la plupart des cas, vous n'avez pas besoin d'utiliser des générateurs dans Kotlin car nous avons des arguments par défaut et nommés. Cela vous permet d'écrire
et utilisez-le comme ceci:
Si vous voulez absolument utiliser des builders, voici comment vous pouvez le faire:
Faire du Builder un
companion object
n'a pas de sens car lesobject
s sont des singletons. Déclarez-la plutôt comme une classe imbriquée (qui est statique par défaut dans Kotlin).Déplacez les propriétés vers le constructeur afin que l'objet puisse également être instancié de la manière habituelle (rendez le constructeur privé s'il ne le devrait pas) et utilisez un constructeur secondaire qui prend un générateur et délègue au constructeur principal. Le code ressemblera à ceci:
Usage:
val car = Car.Builder().model("X").build()
Ce code peut être raccourci en outre en utilisant un DSL de constructeur :
Usage:
val car = Car.build { model = "X" }
Si certaines valeurs sont requises et n'ont pas de valeurs par défaut, vous devez les mettre dans le constructeur du constructeur et également dans la
build
méthode que nous venons de définir:Usage:
val car = Car.build(required = "requiredValue") { model = "X" }
la source
Car.Builder builder = new Car.Builder();
. Cependant, seule la première version a une interface fluide, de sorte que les appels aux deuxième et troisième versions ne peuvent pas être chaînés.Une approche consiste à faire quelque chose comme ce qui suit:
Exemple d'utilisation:
la source
Comme j'utilise la bibliothèque Jackson pour analyser des objets à partir de JSON, j'ai besoin d'un constructeur vide et je ne peux pas avoir de champs facultatifs. Tous les champs doivent également être modifiables. Ensuite, je peux utiliser cette belle syntaxe qui fait la même chose que le modèle Builder:
la source
@JsonProperty
@JsonProperty
, si vous compilez avec le-parameters
commutateur.Personnellement, je n'ai jamais vu de constructeur à Kotlin, mais c'est peut-être juste moi.
Toutes les validations dont on a besoin se produisent dans le
init
bloc:Ici, je me suis permis de deviner que vous ne vouliez pas vraiment
model
etyear
d'être changeant. De plus, ces valeurs par défaut semblent n'avoir aucun sens, (surtoutnull
pourname
) mais j'en ai laissé une à des fins de démonstration.Une opinion: Le modèle de constructeur utilisé en Java pour vivre sans paramètres nommés. Dans les langages avec des paramètres nommés (comme Kotlin ou Python), il est recommandé d'avoir des constructeurs avec de longues listes de paramètres (peut-être facultatifs).
la source
@JvmOverloads
kotlinlang.org/docs/referenceJ'ai vu de nombreux exemples qui déclarent des amusements supplémentaires en tant que constructeurs. J'aime personnellement cette approche. Économisez des efforts pour écrire des générateurs.
Je n'ai pas encore trouvé de moyen de forcer l'initialisation de certains champs dans DSL, comme afficher des erreurs au lieu de lancer des exceptions. Faites-moi savoir si quelqu'un sait.
la source
Pour une classe simple, vous n'avez pas besoin d'un générateur distinct. Vous pouvez utiliser des arguments de constructeur optionnels comme l'a décrit Kirill Rakhman.
Si vous avez une classe plus complexe, Kotlin fournit un moyen de créer des Builders / DSL de style Groovy:
Constructeurs de type sécurisé
Voici un exemple:
Exemple Github - Générateur / Assembleur
la source
Les gens de nos jours devraient vérifier les constructeurs de type Safe de Kotlin .
L'utilisation de cette méthode de création d'objet ressemblera à ceci:
Un bon exemple d'utilisation «en action» est le framework vaadin-on-kotlin , qui utilise des constructeurs sécurisés pour assembler des vues et des composants .
la source
Je suis en retard à la fête. J'ai également rencontré le même dilemme si je devais utiliser le modèle Builder dans le projet. Plus tard, après des recherches, j'ai réalisé que c'était absolument inutile puisque Kotlin fournit déjà les arguments nommés et les arguments par défaut.
Si vous avez vraiment besoin de mettre en œuvre, la réponse de Kirill Rakhman est une réponse solide sur la façon de mettre en œuvre de la manière la plus efficace. Une autre chose que vous pouvez trouver utile est https://www.baeldung.com/kotlin-builder-pattern que vous pouvez comparer et contraster avec Java et Kotlin sur leur implémentation
la source
Je dirais que le modèle et la mise en œuvre restent à peu près les mêmes dans Kotlin. Vous pouvez parfois l'ignorer grâce aux valeurs par défaut, mais pour la création d'objets plus compliqués, les constructeurs sont toujours un outil utile qui ne peut pas être omis.
la source
vous pouvez utiliser le paramètre facultatif dans l'exemple kotlin:
puis
la source
la source
J'ai implémenté un modèle Builder de base dans Kotlin avec le code suivant:
et enfin
Java:
Kotlin:
la source
Je travaillais sur un projet Kotlin qui exposait une API consommée par les clients Java (qui ne peuvent pas tirer parti des constructions du langage Kotlin). Nous avons dû ajouter des générateurs pour les rendre utilisables en Java, j'ai donc créé une annotation @Builder: https://github.com/ThinkingLogic/kotlin-builder-annotation - c'est essentiellement un remplacement de l'annotation Lombok @Builder pour Kotlin.
la source