par , 02/09/2017 à 09h01 (1321 Affichages)
Comme en Java, en Kotlin tout ce qui retourne une valeur est une expression : litéral, opération, appel de fonction ...
On peut aussi combiner déclaration et expressions :
1 2 3 4
|
val a = 10
val b = f(150)
val c = 60*89 |
Là où les choses deviennent intéressantes, c'est l'emploi de certaines structures de contrôles en tant qu'expressions !!!
Je m'explique. Prenons le snippet suivant :
1 2
|
val majeur = if (age < 18) "Non" else "Oui" |
N'y remarquez-vous rien d'étrange ?
Et oui, la structure de contrôle if est bien utilisée comme expression afin d'initialiser la variable majeur. D'ailleurs, au passage, il n'y a pas d'opérateur ternaire en Kotlin : cette syntaxe remplace l'opérateur ternaire.
D'ailleurs je vous ferais remarquer que dans le cas de blocs en lieu et place des branches, la valeur de chaque branche correspond à la valeur de sa dernière ligne (et donc Unit -équivalent de Void- si jamais cette dernière ligne ne retourne aucune valeur) :
1 2 3 4 5 6 7 8 9
|
val majeur = if (age < 18) {
println("Non, accès interdit !")
false
}
else {
println("C'est bon, entrez !")
true
} |
Il va de soi que les différentes branches doivent retourner des valeurs compatibles.
Une autre situation : le mot-clé when :
1 2 3 4 5 6 7 8 9
|
val resultat = java.util.Random().nextInt(21)
println(when (resultat) {
in 0..9 -> "Passable"
in 10..14 -> "Bien"
in 15..18 -> "Très bien"
in 18..20 -> "Excellent et prometteur !"
else -> throw IllegalArgumentException()
}) |
Alors plusieurs remarques sur le code :
- j'utilise directement le résultat de l'expression offerte par when dans la fonction println
- je teste à chaque fois si la valeur figure dans la plage donnée. En effet le mot-clé in permet de tester l'appartenance (de manière générale sur tout itérateur) et 0..9 est une "range", un intervalle valant [0,9] pour les matheux. Pour les autres cela signifie simplement que les valeurs 0 et 9 sont comprises. Enfin, les range en Kotlin n'impliquent que des entiers
- j'utilise une forme générique de when : on peut tester de simples valeurs, des intervalles, le fait que ce soit une instance de telle classe ... Plus d'exemples dessous.
- enfin, si je lance une exception, son type de retour est Nothing, et comme Nothing est considéré comme sous-classe de toutes les classes existantes en Kotlin, cela ne pose aucun problème. Alors que vaut Nothing ? Et bien rien ! En effet, quand je lance une exception le programme s'arrête ou en tout cas la fonction où elle est lancée si il n'y a pas de try/catch
Avant de finir avec l'utilisations de when, il faut être conscient que try/catch/finally est aussi une expression !
1 2 3 4 5 6 7 8
|
val nombre = try {
10 / 0
} catch (e: ArithmeticException){
0
}
println("Nombre vaut $nombre") |
Comme vous l'aurez probablement deviné sans même passer par le playground Kotlin, ce code affiche tout simplement "Nombre vaut 0".
Revenons maintenant, sur le mot-clé when.
1 2 3 4 5 6 7
|
val a = 10
when {
a in -10..3 -> println("Evidement ça ne passe pas ici !")
a < -1 -> println("Là non plus !")
else -> println("C'est bon !")
} |
Ceci est la forme générique du when, sans test de variable direct. Notez bien qu'afin de couvrir tous les cas imaginables, le mot-clé else est ici obligatoire (c'est le default du switch de java). Aussi, on ne peut comparer un Int et un Double en Kotlin (si j'avais précisé `a !is Double` dans l'une des branches, j'aurais eu une erreur de syntaxe). Le trantypage automatique n'existe pas en Kotlin (un choix qui peut paraître honorable).
Cette forme
1 2 3 4 5 6
|
val a = 10
println(when (a) {
in -10..-1, in 1..10 -> "Valeur non nulle"
else -> "Valeur nulle"
}) |
est la forme directe que nous avons déjà rencontré auparavant.
Voilà, j'espère que vous aurez pris du plaisir à lire ce billet
Mis à jour 08/09/2017 à 14h13 par tails
(Ajout : Chaque branche d'une expression a la valeur de sa dernière expression.)
- Catégories
-
Java