J'ai essayé de faire quelque chose comme ce qui suit:
val result = biLet(a, b) { p1, p2 -> p1 + p2 }
mais il ne compile pas car plus
attend un Int
.
J'ai également essayé de créer une fonction biLet:
fun <V1, V2, V3> biLet(a: V1?, b: V2?, block: (V1, V2) -> V3): V3? { return a?.let { b?.let { block(a, b) } } }
et utilisez-le comme ça:
val a: Int? = 1 val b: Int? = 1 a?.plus(b)
mais cela semble beaucoup de travail pour quelque chose d'apparemment simple. Existe-t-il une solution plus simple?
3 Réponses :
Malheureusement, il n'y a déjà rien dans la bibliothèque standard pour additionner deux entiers nullables.
Ce que vous pouvez faire, cependant, est de créer un operator fun
pour un Int?
nullable Int?
:
val a: Int? = 2 val b: Int? = 3 val c = a + b
Et puis, vous pouvez l'utiliser normalement comme la version non nulle:
operator fun Int?.plus(other: Int?): Int? = if (this != null && other != null) this + other else null
Si vous ne souhaitez pas créer de fonction pour lui, vous pouvez toujours utiliser son corps pour gérer la possibilité de nullité des deux entiers.
Eh bien, pour moi, celui-ci a l'air le plus lisible,
val result = (a?:0)+(b?:0)
Et quand l'un est nul, l'autre n'est pas nul et que vous voulez juste la valeur non nulle, alors peut-être comme ceci:
val result = if (a != null && b != null) a+b else null
PS: le second sera égal à 0 si les deux étaient nuls.
C'est certainement le moyen le plus lisible s'il s'agit à la fois de variables locales ou de propriétés en lecture seule. Cela montre clairement le behvaior. Les membres vars seraient plus compliqués. L'idée de la fonction d'opérateur dans l'autre réponse est certes concise, mais masque la façon dont elle traite la nullité, donc je dirais que la lisibilité est discutable. J'irais jusqu'à dire que pour les propriétés var
, vous devez créer des copies val
locales, puis utiliser cette solution. Comportement verbeux, mais très clair.
@ Tenfour04 "L'idée de la fonction d'opérateur dans les réponses est certes concise, mais masque la façon dont elle traite la nullité, donc je dirais que la lisibilité est discutable." Pourriez-vous nous en dire davantage?
@DiegoMarin Je vous ai répondu en haut.
Eh bien, ne sont pas utilisés autant de fois, je ne les ai probablement jamais utilisés uwu.
La réponse dépend vraiment de la sortie attendue de l'ajout de valeurs nulles.
Est-ce que 4 + null = null
ou 4 + null = 4
? et qu'en est-il de null + null
?
Dans mon cas, ce que je voulais, c'est:
4 + 3 = 7
4 + null = 4
null + null = null
La fonction ci-dessous réalise ce comportement
operator fun Int?.plus(other: Int?): Int? { return if (this == null && other == null) { null } else { (a ?: 0) + (b ?: 0) } } ... val a: Int? = 1 val b: Int? = 1 val result = a + b
Vous pouvez également utiliser unesurcharge d'opérateur si vous voulez ce même comportement partout, mais lorsque vous l'utilisez, il n'est pas clair que son comportement est personnalisé.
private fun addNullable(a: Int?, b: Int?): Int? { return if (a == null && b == null) { null } else { (a ?: 0) + (b ?: 0) } } ... val a: Int? = 1 val b: Int? = 1 val result = addNullable(a, b)
b?.let {a?.plus(it)}
fonctionneJ'ai déplacé mon commentaire vers l'une des réponses. Ce que je veux dire, c'est que si je vois
val c = a + b
pour deuxInt
s nullables, ce n'est pas évident sic
est nullable, et ce n'est pas évident ce qui se passe sia
oub
est nullable. Peut-être que l'opérateur+
les rend par défaut à0
quand nul, ou peut-être à-1
, ou peut-être même qu'il lève une IllegalArgumentException. Peut-être qu'il renvoie simplement0
si l'un ou l'autre des nombres estnull
. Ce sont tous des comportements éventuellement souhaités en fonction du contexte. Mais s'il s'agit d'une petite classe et que la fonction d'opérateur est gardée privée pour la classe, ce n'est pas grave.Logique. Je ne suis pas au courant d'une théorie sur les types Nullable qui définit les opérations. Je considérerais raisonnable de définir toute opération entre les types Nullable comme ayant un résultat nul si les deux opérandes sont Null.