web-dev-qa-db-fra.com

La classe de données Kotlin peut-elle avoir plus d'un constructeur?

Je sais que les classes de données sont comme des modèles simples en kotlin avec des getters et setter par défaut et sont aussi simples que ceci:

data class User(val name: String, val age: Int)

Est-il possible de déclarer un deuxième constructeur pour cette classe de données?

29
Eder Padilla

vous pouvez définir la classe de données comme ceci

data class User(val name: String? = null, val id: String? = null, val email: String? = null)

et vous pouvez instance l'objet avec plusieurs constructeurs comme celui-ci

val userId = User(id = "123456")
        val userMail = User(email= "[email protected]")
        val userName = User("Name")
0
Eder Padilla

Oui, mais chaque variable doit être initialisée, vous pouvez donc définir des arguments par défaut dans votre constructeur de classe de données, comme ceci:

data class Person(val age: Int, val name: String = "Person without name")

Vous pouvez maintenant créer une instance de cette classe de données de deux manières

  • Person(30)
  • Person(20, "Bob")
18
Alexey Denysenko

Une classe de données Kotlin doit avoir un constructeur principal qui définit au moins un membre. En dehors de cela, vous pouvez ajouter des constructeurs secondaires comme expliqué dans Classes et héritage - Constructeurs secondaires .

Pour votre classe et exemple de constructeur secondaire:

data class User(val name: String, val age: Int) {
    constructor(name: String): this(name, -1) { ... }
}

Notez que le constructeur secondaire doit déléguer au constructeur principal dans sa définition.

Bien que beaucoup de choses communes aux constructeurs secondaires puissent être résolues en ayant des valeurs par défaut pour les paramètres. Dans le cas ci-dessus, vous pouvez simplifier pour:

data class User(val name: String, val age: Int = -1) 

Si vous les appelez depuis Java, vous devriez lire la documentation Java interop - Java appel Kotlin sur la façon de générer des surcharges, et peut-être parfois le NoArg Compiler Plugin pour les autres cas particuliers.

18
Jayson Minard

Réponse mise à jour pour les classes de données:

Oui, vous pouvez, mais vous devrez tout déléguer au constructeur principal

data class User(val name: String, val age: Int)
{
    constructor(name: String): this(name, -1) {
    }

    constructor(age: Int): this("Anon", age) {
    }
}

// Anon name: Anon
println("Anon name: " + User(30).name)

// No age: -1
println("No age: " + User("Name").age)

// Name: Name age: 20
val u = User("Name", 20)
println("Name: " + u.name + " age: " + u.age)

Vous pouvez également définir des valeurs par défaut dans votre constructeur principal, comme l'a fait Alexey.

4
Robert

Oui, nous pouvons utiliser comme ci-dessous le code, et dans le constructeur principal pour la classe de données doit avoir au moins un paramètre.

data class SampleData(val name: String, val age: Int) {
    constructor(name: String, age: Int, email: String) : this(name, age) {

    }
}

Les valeurs par défaut dans le constructeur principal éliminent de nombreux besoins pour les constructeurs secondaires, mais si l'instance nécessaire dépend d'une logique basée sur des données qui doivent être analysées, la meilleure réponse peut être d'utiliser un objet compagnon.

data class KeyTag(val a: String, val b: Int, val c: Double) {
    companion object Factory {
        val empty = KeyTag("", 0, 0.0)

        fun create(bigString: String): KeyTag {
            // Logic to extract appropriate values for arguments a, b, c
            return KeyTag(a, b, c)
        }

        fun bake(i: Int): KeyTag = KeyTag("$i", i, i.toDouble())
    }
}

L'utilisation est alors:

val ks = KeyTag.create("abc:1:10.0")
val ke = KeyTag.empty
val kb = KeyTag.bake(2)
1
Mike Hanafey

La classe de données garantira la cohérence et un comportement significatif, nous devons également avoir une valeur pour l'immuabilité.

data class SampleData(val name: String, val age: Int, val email: String ?= null) {
constructor(name: String, age: Int) : this(name, age, null) {

}

}

le constructeur secondaire doit déléguer au constructeur principal dans sa définition, donc pour maintenir l'immuabilité, avoir "null" fonctionnera.

0
boopathiraja

Demande au compilateur Kotlin de générer des surcharges pour cette fonction qui remplacent les valeurs de paramètre par défaut. Si une méthode a N paramètres et dont M ont des valeurs par défaut, M surcharges sont générées: la première prend N-1 paramètres (tous sauf le dernier qui prend une valeur par défaut), la seconde prend N-2 paramètres, etc. sur.

data class User @JvmOverloads  constructor(
var email: String="",
var password: String=""

)

0
RanaUmer