55 votes

Existe-t-il un moyen d'utiliser la valeur par défaut d'un paramètre non facultatif lorsque la valeur nulle est transmise ?

Par exemple, si j'ai la classe de données suivante :

data class Data(
    val name: String = "",
    val number: Long = 0
)

Et les fonctions qui peuvent retourner null :

fun newName(): String? {}

fun newNumber(): Long? {}

Je sais que je peux utiliser ce qui suit pour utiliser la valeur des fonctions si elles ne sont pas null :

val newName = newName()
val newNumber = newNumber()

val data = Data(
        if (newName != null) newName else "",
        if (newNumber != null) newNumber else 0
)

Mais existe-t-il un moyen d'utiliser simplement la valeur par défaut spécifiée dans le constructeur de l'application Data lorsque les valeurs sont null ?

Je n'ai rien trouvé dans la documentation, mais j'espérais que quelque chose comme ça fonctionnerait :

val data = Data(newName()?, newNumber()?)

Mais cela ne compile pas.

3 votes

Au lieu de if (newName != null) newName else "" vous pouvez simplement utiliser newName ?: "" . Ça s'appelle l'opérateur Elvis.

0 votes

@Mibac Oh, c'est vrai, j'ai oublié ça ! C'est définitivement plus succinct, mais ça n'utilise toujours pas le paramètre par défaut défini dans le constructeur de la classe.

45voto

mfulton26 Points 1609

Vous pouvez définir un objet compagnon pour votre classe de données et surcharge son invoquer l'opérateur pour utiliser les valeurs par défaut lorsque null est adoptée :

data class Data private constructor(
    val name: String,
    val number: Long
) {
    companion object {
        operator fun invoke(
            name: String? = null,
            number: Long? = null
        ) = Data(
            name ?: "",
            number ?: 0
        )
    }
}

9 votes

Oh, c'est une belle solution de rechange ! Mais j'aurais aimé que quelque chose de ce genre soit intégré au langage, ne serait-ce que pour se débarrasser du texte passe-partout.

0 votes

Cela fonctionnera-t-il si l'on supprime la deuxième propriété (le nombre) ? J'obtiens une erreur de compilation pour data class Data(val name: String = "") { constructor(name: String? = null) : this(name ?: "") }

0 votes

Je pense que vous devrez passer dans null ou ajouter un autre constructeur secondaire, par exemple. constructor(): this("")

22voto

holi-java Points 15887

Le constructeur secondaire ne supporte que les propriétés primitives Nullable. ce qui signifie qu'il y aura 2 constructeurs identiques si la propriété n'est pas un type primitif, par exemple :

data class Data(val name: String) {
    constructor(name: String? = null) : this(name ?: "foo");
    // ^--- report constructor signature error                
}

data class Data(val number: Long = 0) {
     constructor(number: Long? = null) : this(number ?: 0)
     //                  ^--- No problem since there are 2 constructors generated:
     //                       Data(long number) and Data(java.lang.Long number)
}

Une autre solution consiste à utiliser invoke opérateur pour cela, par exemple :

data class Data(val name: String) {
    companion object {
        operator fun invoke(name: String? = null) = Data(name ?: "")
    }
}

SI la classe n'est pas une classe de données, alors vous pouvez paresseusement initialiser les propriétés à partir des paramètres, plutôt que de définir des propriétés sur le constructeur primaire, par exemple :

class Data(name: String? = null, number: Long? = null) {
    val name = name ?: ""
    val number = number ?: 0
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X