Apprendre les bases de Kotlin

Ici, vous trouverez toutes les ressources nécessaires pour apprendre et maîtriser le langage de programmation Kotlin. Que vous soyez un débutant en développement Android ou un développeur expérimenté, ce site vous aidera à acquérir les bases de Kotlin et à tirer le meilleur parti de ce langage moderne et expressif

Vous découvrirez des tutoriels détaillés, des exemples de code, des bonnes pratiques et des astuches sur les sujets clés de Kotlin, notamment :

  • Variables : Déclaration et utilisation de variables en Kotlin

  • Types de base : Comprendre les types de données de base du langage

  • Collections : Travailler avec les listes, sets et maps Kotlin

  • Contrôle de flux : Conditions, boucles et autres structures de contrôle

  • Fonctions : Création et utilisation de fonctions en Kotlin

  • Classes : Définition de classes et d'objets Kotlin

  • Null safety : Gérer les valeurs potentiellement nulles

Introduction

Une brève histoire et ses utilisations

Naissance et évolution Kotlin est un langage de programmation moderne développé par JetBrains, une société russe spécialisée dans les outils de développement logiciel. Son histoire débute en 2010, lorsque l'équipe de JetBrains commence à explorer des alternatives au langage Java, populaire mais parfois verbeux et complexe.

L'objectif était de créer un langage de programmation concis, sûr, interopérable avec Java et capable de s'exécuter sur la machine virtuelle Java (JVM). La première version officielle de Kotlin est sortie en 2016, et depuis lors, elle a connu une adoption croissante dans la communauté des développeurs.

Motivation

Les créateurs de Kotlin, dont Andrey Breslav et Dmitry Jemerov, étaient motivés par le désir de créer un langage qui offrirait les avantages suivants :

  • Concision: Kotlin est conçu pour être un langage plus concis que Java, permettant d'écrire du code plus court et plus lisible.

  • Sécurité: Kotlin intègre des fonctionnalités de sécurité telles que la prise en charge du typage statique et des vérifications nulles pour réduire les erreurs de programmation courantes.

  • Interopérabilité: Kotlin est entièrement interopérable avec Java, ce qui signifie que les développeurs peuvent facilement utiliser des bibliothèques et des frameworks Java existants dans leurs projets Kotlin.

  • Performance: Kotlin est compilé en code Java bytecode, ce qui lui permet de s'exécuter aussi rapidement que Java sur la JVM.

Utilisation

Kotlin est un langage polyvalent qui peut être utilisé pour développer une large gamme d'applications, notamment :

  • Applications Android: Kotlin est le langage de programmation officiel pour le développement d'applications Android, et il est largement utilisé par les développeurs Android pour créer des applications mobiles natives.

  • Applications web: Kotlin peut être utilisé pour développer des applications web back-end avec des frameworks tels que Spring Boot et Ktor.

  • Applications de bureau: Kotlin peut être utilisé pour développer des applications de bureau multiplateformes avec des frameworks tels que JavaFX et Kotlin Multiplatform Mobile (KMM).

  • Développement multiplateforme: KMM permet aux développeurs d'écrire du code Kotlin partageable entre les plateformes Android et iOS, simplifiant ainsi le développement d'applications mobiles multiplateformes.

Installation et utilisation

Installation avec IntelliJ IDEA:

IntelliJ IDEA est un environnement de développement intégré (IDE) populaire qui offre un support complet pour Kotlin. Il fournit des fonctionnalités telles que la coloration syntaxique, la complétion de code, la refactorisation et le débogage, ce qui facilite le développement d'applications Kotlin.

  1. Téléchargez et installez le plugin Kotlin pour IntelliJ IDEA.

  2. Configurez le projet pour utiliser Kotlin en tant que langage de programmation.

  3. Commencez à écrire du code Kotlin !

Compilation

Le code Kotlin est compilé en code Java bytecode, qui peut ensuite être exécuté sur la JVM. La compilation se fait généralement à l'aide d'un compilateur Kotlin, tel que le compilateur Kotlin de ligne de commande (kotlinc) ou le compilateur intégré à IntelliJ IDEA.

Installation avec un compilateur en ligne

De nombreux compilateurs en ligne supportent Kotlin, tels que Kotlin Playground: https://play.kotlinlang.org/ et Repl.it: https://repl.it/languages/kotlin. Vous pouvez coller votre code Kotlin dans ces outils et l'exécuter directement dans votre navigateur web.

Voici un programme simple qui affiche "Hello, world!" :

fun main() {
    println("Hello, world!")
}

Variables

Les variables permettent de stocker et de manipuler facilement des données dans un programme Kotlin. Par exemple, si vous voulez afficher un message de bienvenue avec le nom de l'utilisateur, vous pouvez déclarer une variable pour stocker son nom, puis l'utiliser pour construire le message à afficher. Cela vous donne un moyen flexible et réutilisable de travailler avec ces informations.

  • Variables en lecture seule avec val

  • Variables mutables avec var

Pour assigner une valeur, utilisez l'opérateur d'affectation =.

Par exemple:

val popcorn = 5
val hotdog = 7 
var clients = 10 

clients = 8
println(clients)
// 8

Comme clients est une variable mutable, sa valeur peut être réassignée après la déclaration.

😉
Nous vous recommandons de déclarer toutes les variables en lecture seule (val) par défaut. Ne déclarez des variables mutables (var) que si c'est nécessaire.
Les variables peuvent être déclarées en dehors de la fonction main() au début de votre programme.

Les commentaires

Un histoire

Voici l'histoire de Tshaba, le développeur qui n'aimait pas les commentaires :

Il y a 2 mois, Tshaba, un jeune développeur plein d'ambition, a terminé un projet important pour son entreprise. Fier de son travail, il a livré le code sans ajouter le moindre commentaire. "Qui en a besoin de toute façon ?" pensait-il, "Mon code est tellement bien organisé, personne ne devrait avoir de mal à le comprendre."

Satisfait de son travail, Tshaba s'est ensuite lancé dans de nouveaux défis, laissant derrière lui ce projet "terminé". Mais voilà qu'aujourd'hui, son patron lui demande d'apporter une petite modification urgente sur ce fameux code.

Tshaba se gratte la tête, perplexe. "Quel était le rôle de cette fonction déjà ? Et pourquoi ai-je utilisé cette structure de données complexe ?" Malgré ses efforts, il peine à se rappeler la logique derrière chaque partie du code. "Si seulement j'avais pris le temps d'ajouter quelques commentaires !" se lamente-t-il.

Passant d'un fichier à l'autre, Tshaba doit reconstituer mentalement le fonctionnement de son propre programme, perdant un temps précieux. "Plus jamais je ne commettrai cette erreur !" se jure-t-il. À partir de maintenant, il s'engage à documenter soigneusement son code, pour éviter de se retrouver dans une telle situation à l'avenir.

Morale de l'histoire : les commentaires sont essentiels pour faciliter la compréhension et la maintenance du code, surtout sur le long terme. Tshaba a appris cette leçon à ses dépens, mais vous pouvez éviter de répéter la même erreur !

Les commentaires sont des éléments du code qui ne sont pas exécutés par le programme, mais qui servent à documenter et à expliquer le code pour les autres développeurs (ou pour soi-même plus tard).

En Kotlin, il existe trois types de commentaires :

Commentaires simples d'une ligne :

// Ceci est un commentaire sur une seule ligne

Ce type de commentaire commence par les deux barres obliques // et s'étend jusqu'à la fin de la ligne.

Commentaires multi-lignes :

/*
 * Ceci est un commentaire
 * sur plusieurs lignes.
 * Chaque ligne commence par une étoile.
 */

Ce type de commentaire commence par /* et se termine par /. Chaque ligne intermédiaire commence par une étoile .

Commentaires de documentation :

/**
 * Ceci est un commentaire de documentation.
 * Il est utilisé pour documenter des éléments de code
 * comme des fonctions, des classes ou des propriétés.
 * @param name le nom de l'utilisateur
 * @param email l'adresse email de l'utilisateur
 * @return l'objet User créé
 */
fun createUser(name: String, email: String): User {
    return User(name, email)
}

Les commentaires de documentation commencent par /** et se terminent par */. Ils sont souvent utilisés pour documenter la signature des fonctions, leurs paramètres et leurs valeurs de retour. Ils peuvent être traités par des outils comme Dokka pour générer une documentation automatique.

val popcorn = 5    // Il y a 5 boîtes de pop-corn.
val hotdog = 7     // Il y a 7 hot-dogs.
var clients = 10 // Il y a 10 clients dans la file d'attente.

// Certains clients quittent la file d'attente.
clients = 8
println(clients)
// 8

Par example:

val clinets = 10
println("Il y a $clients clients.")
// Il y a 10 clients

println("Il y a ${clients + 1} clients")
// Il y a 11 clients

Pour plus d'informations, consultez la section sur les templates de chaînes de caractères.

Vous remarquerez qu'il n'y a pas de types déclarés pour les variables. Kotlin a inféré le type lui-même : Int. La suite de ce tutoriel expliquera les différents types de base de Kotlin et comment les déclarer dans le prochain chapitre.

Pratique

Mission

Nous voulons créer une application pour gérer des événements. Dans l'application, les utilisateurs pourront s'inscrire et publier des événements.

En tant que développeur, votre mission est de créer en premier temps un programme qui affiche le nom d'un utilisateur et son adresse email.

Complétez le code pour afficher "Nom : zgenius, email : zgeniuscoders@gmail.com" à la sortie standard.

fun main() {
    val nom = "zgenius"
    val email = "zgeniuscoders@gmail.com"
}

Types de bases

Chaque variable et structure de données en Kotlin a un type de données. Les types de données sont importants car ils indiquent au compilateur ce que vous êtes autorisé à faire avec cette variable ou structure de données. En d'autres termes, quelles fonctions et propriétés elle possède.

Dans le chapitre précédent, Kotlin a pu déduire que clients avait le type Int. La capacité de Kotlin à déduire le type de données s'appelle l'inférence de type. clients est assigné à une valeur entière. À partir de cela, Kotlin déduit que clients a un type de données numérique : Int. Par conséquent, le compilateur sait que vous pouvez effectuer des opérations arithmétiques avec clients :

var clients = 10

// Certains clients quittent la file d'attente.
clients = 8

clients = clients + 3 // Exemple d'addition : 11
clients += 7            // Exemple d'addition : 18
clients -= 3            // Exemple de soustraction : 15
clients *= 2            // Exemple de multiplication : 30
clients /= 3            // Exemple de division : 10

println(clients) // 10

+=, -=, *=, /= et %= sont des opérateurs spéciaux en Kotlin qui permettent d'effectuer une opération arithmétique et d'assigner le résultat à la même variable en une seule étape

Par exemple, l'expression x += 5 est équivalente à x = x + 5. Elle permet d'ajouter 5 à la valeur de la variable x et d'affecter le résultat à x.

De même, x -= 3 est équivalent à x = x - 3, x \= 2 à x = x 2, x /= 4 à x = x / 4 et x %= 6 à x = x % 6.

Ces opérateurs d'assignation augmentée rendent le code plus concis et lisible lorsqu'on effectue ce type d'opérations courantes sur une variable.

Types

En tout, Kotlin a les types de base suivants :

CategoryBasic types
EntiersByte, Short, Int, Long
Entiers non signésUByte, UShort, UInt, ULong
Nombres à virgule flottanteFloat, Double
BooléensBoolean
CaractèresChar
Chaînes de caractèresString

Entiers (Int)

val age = 25

Le type Int représente un nombre entier, positif ou négatif. Il peut stocker des valeurs de -2 147 483 648 à 2 147 483 647.

Booléens (Boolean)

val estMineur = false

Le type Boolean ne peut prendre que deux valeurs possibles : true (vrai) ou false (faux). Il est souvent utilisé pour représenter des conditions.

Nombres à virgule flottante (Double)

val pi = 3.14159

Le type Double représente un nombre à virgule flottante, c'est-à-dire un nombre décimal. Il peut stocker des valeurs avec une grande précision.

Chaînes de caractères (String)

val nom = "John"

Le type String sert à représenter du texte. Les chaînes de caractères peuvent contenir des lettres, des chiffres et des symboles.

Caractères (Char)

val lettre  = 'A'

Le type Char représente un seul caractère, comme une lettre, un chiffre ou un symbole. Les valeurs de type Char sont délimitées par des apostrophes simples '.

Déclaration et initialisation de variables

Avec ces connaissances, vous pouvez déclarer des variables et les initialiser plus tard. Kotlin peut gérer cela tant que les variables sont initialisées avant la première lecture.

Pour déclarer une variable sans l'initialiser, spécifiez son type avec :.

Par exemple :

// Variable déclarée sans initialisation 
val d: Int
// Variable initialisée
d = 3

// Variable explicitement typée et initialisée
val e: String = "hello"

// une fois les variables initialisées, elles peuvent être lues.
println(d) // 3
println(e) // hello

Maintenant que vous connaissez comment déclarer les types de base, il est temps d'apprendre à travailler avec les collections.

Pratique

Mission 2

Déclarez explicitement le type correct pour chaque variable :

fun main() {
    val nom_utilisateur = "zgeniuscoders"
    val age = 18
    val poids = 64.3
    val estMineur = false
}

Correction mission 1

Nous voulons créer une application pour gérer des événements. Dans l'application, les utilisateurs pourront s'inscrire et publier des événements.

En tant que développeur, votre mission est de créer en premier temps un programme qui affiche le nom d'un utilisateur et son adresse email.

Complétez le code pour afficher "Nom : zgenius, email : zgeniuscoders@gmail.com" à la sortie standard.

fun main() {
    val name = "zgenius"
    val email = "zgeniuscoders@gmail.com"
    println("Nom : $name, email : $email")
}

Les Collections

Histoire

Voici l'histoire de Tshaba et de son exploration des collections en Kotlin :

Tshaba, le développeur consciencieux, travaillait sur un nouveau projet passionnant. Il devait gérer une grande quantité de données sur les activités de son entreprise. Au début, il enregistrait simplement chaque information dans des variables séparées, mais très vite, il s'est rendu compte que ce système devenait ingérable.

"Il faut que je trouve un moyen de mieux organiser toutes ces données !" s'est-il exclamé, en grattant sa tête bouclée.

C'est alors qu'il a découvert les collections offertes par le langage Kotlin. Fasciné, Tshaba s'est plongé dans l'exploration de ces structures de données puissantes.

Tout d'abord, il a appris à utiliser les listes pour stocker de manière ordonnée les informations sur les activités de son entreprise. Plus besoin de se souvenir d'un index pour accéder à une donnée spécifique !

Ensuite, il s'est initié aux sets, qui lui ont permis de n'enregistrer qu'une seule fois chaque type d'activité, évitant ainsi les doublons.

Puis, les maps sont devenues son arme favorite pour associer les noms d'employés à leurs activités respectives. Fini les recherches fastidieuses, il pouvait maintenant accéder instantanément aux informations dont il avait besoin.

Tshaba était ravi de la puissance et de la flexibilité offertes par ces collections Kotlin. Grâce à elles, il a pu organiser efficacement toutes ses données et les traiter avec aisance.

"Quel progrès par rapport à mes anciennes méthodes !" s'est-il félicité. Désormais, Tshaba était bien décidé à exploiter au maximum les collections pour tous ses futurs projets de développement.

Lors de la programmation, il est utile de pouvoir regrouper des données dans des structures pour les traiter ultérieurement. Kotlin fournit des collections exactement dans ce but.

Kotlin dispose des collections suivantes pour regrouper les éléments :

Collection typeDescription
ListsReprésente une séquence ordonnée d'éléments. Les listes sont mutables et les éléments peuvent être accédés par leur index.
SetsReprésente un ensemble d'éléments uniques. Les sets sont utiles lorsque vous souhaitez stocker des valeurs sans doublons.
MapsReprésente une collection de paires clé-valeur. Les maps permettent d'associer des clés à des valeurs pour un accès rapide.

Chaque type de collection en Kotlin peut être soit :

  • Mutable (Modifiable) : Dans ce cas, les éléments de la collection peuvent être ajoutés, modifiés ou supprimés.

  • Read-only (En lecture seule) : Dans ce cas, les éléments de la collection ne peuvent pas être modifiés, seule la lecture est possible.

List

Les Listes (Lists) stockent les éléments dans l'ordre où ils sont ajoutés, et permettent les doublons. Pour créer une liste en lecture seule (List), utilisez la fonction listOf(). Pour créer une liste modifiable (MutableList), utilisez la fonction mutableListOf().

Lors de la création de listes, Kotlin peut déduire le type des éléments stockés. Pour déclarer le type explicitement, ajoutez le type entre chevrons <> après la déclaration de la liste :

// Liste en lecture seule
val readOnlyShapes = listOf("triangle", "square", "circle")
println(readOnlyShapes)
// [triangle, square, circle]

// Liste modifiable avec déclaration de type explicite
val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle") 
println(shapes)
// [triangle, square, circle]

::alert{type="info"} Pour empêcher les modifications non désirées, vous pouvez obtenir des vues en lecture seule de listes mutables en les affectant à une List :

val shapes: MutableList<String> = mutableListOf("triangle", "carré", "cercle")
val shapesLocked: List<String> = shapes

ce processus est également appelé "casting" ::

Les listes étant ordonnées, on peut accéder à un élément spécifique en utilisant l'opérateur d'accès par index [] :

val readOnlyShapes = listOf("triangle", "carré", "cercle")
println("Le premier élément de la liste est : ${readOnlyShapes[0]}")
// Le premier élément de la liste est : triangle

Pour récupérer le premier ou le dernier élément d'une liste, on peut utiliser les fonctions .first() et .last() respectivement :

val readOnlyShapes = listOf("triangle", "carré", "cercle")
println("Le premier élément de la liste est : ${readOnlyShapes.first()}")
// Le premier élément de la liste est : triangle

.first() et .last() sont des exemples de fonctions d'extension. Pour appeler une fonction d'extension sur un objet, écrivez le nom de la fonction après l'objet en le faisant suivre d'un point `.

Pour plus d'informations sur les fonctions d'extension, consultez la section sur les Fonctions d'extension. Pour les besoins de ce tutoriel, vous n'avez besoin de savoir que comment les appeler.

Pour obtenir le nombre d'éléments dans une liste, utilisez la fonction .count() :

val readOnlyShapes = listOf("triangle", "carré", "cercle")
println("Il y a ${readOnlyShapes.count()} éléments dans la liste.")
// Il y a 3 éléments dans la liste.

Pour vérifier qu'un élément est présent dans une liste, utilisez l'opérateur in :

val readOnlyShapes = listOf("triangle", "carré", "cercle")
println("cercle" in readOnlyShapes)
// true

Pour ajouter ou supprimer des éléments d'une liste mutable, utilisez respectivement les fonctions .add() et .remove() :

val shapes: MutableList<String> = mutableListOf("triangle", "carré", "cercle")
// Ajouter "pentagone" à la liste
shapes.add("pentagone")
println(shapes)
// [triangle, carré, cercle, pentagone]

// Supprimer le premier "pentagone" de la liste
shapes.remove("pentagone")
println(shapes)
// [triangle, carré, cercle]

L'opérateur in permet de vérifier efficacement la présence d'un élément dans une liste, tandis que les fonctions .add() et .remove() permettent de modifier dynamiquement le contenu d'une liste mutable."

Set

Alors que les listes sont ordonnées et peuvent contenir des éléments en double, les ensembles (sets) sont non ordonnés et ne stockent que des éléments uniques.

Pour créer un ensemble en lecture seule (Set), utilisez la fonction setOf().

Pour créer un ensemble mutable (MutableSet), utilisez la fonction mutableSetOf().

Lors de la création d'ensembles, Kotlin peut déduire le type des éléments stockés. Pour déclarer explicitement le type, ajoutez-le entre les chevrons <> après la déclaration de l'ensemble :

// Ensemble en lecture seule
val readOnlyFruit = setOf("pomme", "banane", "cerise", "cerise")
// Ensemble mutable avec déclaration de type explicite
val fruit: MutableSet<String> = mutableSetOf("pomme", "banane", "cerise", "cerise")

println(readOnlyFruit)
// [pomme, banane, cerise]

Comme vous pouvez le voir dans l'exemple précédent, les ensembles ne contenant que des éléments uniques, le doublon "cerise" est supprimé."

::alert{type="info"} Pour empêcher les modifications indésirables, obtenez des vues en lecture seule d'ensembles mutables en les convertissant en Set :

val fruit: MutableSet<String> = mutableSetOf("pomme", "banane", "cerise", "cerise")
val fruitLock: Set<String> = fruit

En convertissant fruit en fruitLock, vous obtenez une vue en lecture seule de l'ensemble fruit. Cela vous permet de partager l'ensemble tout en empêchant les modifications indésirables par d'autres parties du code." ::

::alert{type="success"} Comme les sets sont non ordonnés, vous ne pouvez pas accéder à un élément à un index particulier. ::

Contrairement aux listes, les sets ne possèdent pas d'ordre spécifique pour leurs éléments. Par conséquent, il n'est pas possible d'accéder à un élément en utilisant un index. Les sets offrent plutôt des méthodes pour vérifier l'existence d'un élément (contains()), ajouter ou supprimer des éléments, mais pas pour accéder à un élément à une position donnée.

Si vous avez besoin d'accéder à des éléments par leur position, vous devriez plutôt utiliser une liste (List) qui conserve l'ordre de ses éléments.

Pour obtenir le nombre d'éléments dans un ensemble (sets), utilisez la fonction .count() :

val readOnlyFruit = setOf("pomme", "banane", "cerise")
println("Il y a ${readOnlyFruit.count()} éléments dans l'ensemble.")
// Il y a 3 éléments dans l'ensemble.

Pour vérifier qu'un élément est présent dans un ensemble, utilisez l'opérateur in :

val readOnlyFruit = setOf("pomme", "banane", "cerise", "cerise")
println("banane" in readOnlyFruit)
// true

Pour ajouter ou supprimer des éléments d'un ensemble mutable, utilisez respectivement les fonctions .add() et .remove() :

val fruit: MutableSet<String> = mutableSetOf("pomme", "banane", "cerise", "cerise")
fruit.add("fruit du dragon") // Ajouter "fruit du dragon" à l'ensemble
println(fruit)              // [pomme, banane, cerise, fruit du dragon]

fruit.remove("fruit du dragon") // Supprimer "fruit du dragon" de l'ensemble
println(fruit)

Map

Les dictionnaires (maps) stockent les éléments sous forme de paires clé-valeur. Vous accédez à la valeur en référençant la clé. Vous pouvez imaginer un dictionnaire comme un menu de restaurant. Vous pouvez trouver le prix (valeur) en trouvant le plat (clé) que vous voulez manger. Les dictionnaires sont utiles si vous voulez rechercher une valeur sans utiliser un index numérique, comme dans une liste.

  • Chaque clé dans un dictionnaire (map) doit être unique afin que Kotlin puisse comprendre quelle valeur vous voulez obtenir.

  • Vous pouvez avoir des valeurs en double dans un dictionnaire (map).

Pour créer un dictionnaire (map) en lecture seule, utilisez la fonction mapOf().

Pour créer un dictionnaire (map) mutable, utilisez la fonction mutableMapOf().

Lors de la création de dictionnaires, Kotlin peut déduire les types des éléments stockés. Pour déclarer explicitement les types, ajoutez les types des clés et des valeurs entre crochets <> après la déclaration du dictionnaire. Par exemple : MutableMap<String, Int>. Les clés ont le type String et les valeurs ont le type Int.

La façon la plus simple de créer des dictionnaires est d'utiliser to entre chaque clé et sa valeur associée :

// Dictionnaire en lecture seule
val readOnlyJuiceMenu = mapOf("pomme" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu)
// {pomme=100, kiwi=190, orange=100}

// Dictionnaire mutable avec déclaration de type explicite
val juiceMenu: MutableMap<String, Int> = mutableMapOf("pomme" to 100, "kiwi" to 190, "orange" to 100)
println(juiceMenu)
// {pomme=100, kiwi=190, orange=100}

::alert{type="info"} Pour empêcher les modifications non souhaitées, obtenez des vues en lecture seule de dictionnaires mutables en les convertissant en Map :

val juiceMenu: MutableMap<String, Int> = mutableMapOf("pomme" to 100, "kiwi" to 190, "orange" to 100)
val juiceMenuLocked: Map<String, Int> = juiceMenu

::

Dans cet exemple, juiceMenu est un dictionnaire mutable, ce qui signifie que ses éléments peuvent être modifiés. Cependant, en le convertissant en Map via l'affectation juiceMenuLocked, on obtient une vue en lecture seule du même dictionnaire.

Ainsi, juiceMenuLocked n'aura pas les méthodes de modification du dictionnaire mutable, comme put() ou remove(). Il sera donc impossible de modifier le contenu du dictionnaire via cette référence en lecture seule."

Pour accéder à une valeur dans un dictionnaire, utilisez l'opérateur d'accès par index [] avec sa clé :

val juiceMenu: MutableMap<String, Int> = mutableMapOf("pomme" to 100, "kiwi" to 190, "orange" to 100)

// Accès à une valeur
val applePrice = juiceMenu["pomme"] // Renvoie 100
val kiwiPrice = juiceMenu["kiwi"] // Renvoie 190

// Accès à une clé qui n'existe pas
val grapePrice = juiceMenu["raisin"] // Renvoie null

Dans cet exemple, nous accédons aux valeurs associées aux clés "pomme" et "kiwi" dans le dictionnaire juiceMenu.

Si on tente d'accéder à une clé qui n'existe pas dans le dictionnaire, la méthode renvoie null.

Pour obtenir le nombre d'éléments dans un dictionnaire, utilisez la fonction .count() :

// Dictionnaire en lecture seule
val readOnlyJuiceMenu = mapOf("pomme" to 100, "kiwi" to 190, "orange" to 100)
println("Ce dictionnaire a ${readOnlyJuiceMenu.count()} paires clé-valeur")
// Ce dictionnaire a 3 paires clé-valeur

Pour ajouter ou supprimer des éléments dans un dictionnaire mutable, utilisez respectivement les fonctions .put() et .remove() :

val juiceMenu: MutableMap<String, Int> = mutableMapOf("pomme" to 100, "kiwi" to 190, "orange" to 100)
juiceMenu.put("noix de coco", 150) // Ajouter la clé "noix de coco" avec la valeur 150 au dictionnaire
println(juiceMenu)
// {pomme=100, kiwi=190, orange=100, noix de coco=150}

juiceMenu.remove("orange")    // Supprimer la clé "orange" du dictionnaire
println(juiceMenu)
// {pomme=100, kiwi=190, noix de coco=150}

Pour vérifier si une clé spécifique est déjà incluse dans un dictionnaire, utilisez la fonction .containsKey() :

val readOnlyJuiceMenu = mapOf("pomme" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu.containsKey("kiwi"))
// true

Pour obtenir une collection des clés ou des valeurs d'un dictionnaire, utilisez respectivement les propriétés keys et values :

val readOnlyJuiceMenu = mapOf("pomme" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu.keys)
// [pomme, kiwi, orange]
println(readOnlyJuiceMenu.values)
// [100, 190, 100]

Les propriétés keys et values sont des exemples de propriétés d'un objet. Pour accéder à la propriété d'un objet, écrivez le nom de la propriété après l'objet suivi d'un point ..

Les propriétés sont discutées de manière plus détaillée dans le chapitre sur les classes. À cette étape du parcours, vous n'avez besoin de connaître que la façon d'y accéder.

Pour vérifier qu'une clé ou une valeur est présente dans un dictionnaire, utilisez l'opérateur in :

val readOnlyJuiceMenu = mapOf("pomme" to 100, "kiwi" to 190, "orange" to 100)
println("orange" in readOnlyJuiceMenu.keys)
// true
println(200 in readOnlyJuiceMenu.values)
// false

Dans cet exemple, nous vérifions d'abord si la clé "orange" fait partie des clés du dictionnaire readOnlyJuiceMenu, ce qui est vrai. Ensuite, nous vérifions si la valeur 200 fait partie des valeurs du dictionnaire, ce qui est faux.

Pour en savoir plus sur ce que vous pouvez faire avec les collections, consultez la section sur les Collections.

Maintenant que vous connaissez les types de base et comment gérer les collections, il est temps d'explorer les structures de contrôle que vous pouvez utiliser dans vos programmes.

Pratique

Mission 3

Vous disposez d'un ensemble de protocoles pris en charge par votre serveur. Un utilisateur demande à utiliser un protocole particulier. Complétez le programme pour vérifier si le protocole demandé est pris en charge ou non (isSupported doit être une valeur booléenne).

fun main() {
    val SUPPORTED = setOf("HTTP", "HTTPS", "FTP")
    val requested = "smtp"
    val isSupported = // Write your code here 
    println("Support for $requested: $isSupported")
}

Correction Mission 2

Déclarez explicitement le type correct pour chaque variable :

fun main() {
    val nom_utilisateur: String = "zgeniuscoders"
    val age: Int = 18
    val poids: Double = 64.3
    val estMineur: Boolean = false
}

Control flow

Histoire

Tshaba et la Magie des Boucles: Comment un Développeur a Transformé sa Routine en Succès

Tshaba, développeur passionné, travaillait dans une entreprise dynamique. Chaque jour, il accomplissait une tâche fastidieuse : afficher la liste des employés, un par un, dans l'application de l'entreprise. Cette corvée répétitive lui prenait un temps précieux qu'il aurait préféré consacrer à des projets plus stimulants.

Un jour, alors qu'il parcourait un manuel de programmation, Tshaba tomba sur un concept qui changea sa vie professionnelle : les boucles. Intrigué, il plongea dans >l'apprentissage de ces structures puissantes qui lui permettraient d'automatiser sa tâche ingrate.

Avec enthousiasme, Tshaba s'attela à la modification de son code. Il créa une boucle qui parcourait la liste des employés, les affichant un par un à l'écran. Un sentiment de satisfaction l'envahit lorsqu'il exécuta le code. En quelques lignes, il avait automatisé une tâche qui lui prenait auparavant des heures entières.

Comme d'autres langages de programmation, Kotlin est capable de prendre des décisions en fonction de l'évaluation d'un morceau de code comme étant vrai ou faux. Ces morceaux de code sont appelés expressions conditionnelles. Kotlin est également capable de créer et d'itérer des boucles.

Expressions conditionnelles

Kotlin propose les instructions if et when pour vérifier les expressions conditionnelles.

::alert{type="info"}

Quand utiliser if ou when En général, il est recommandé d'utiliser when car cela conduit à des programmes plus robustes et plus sûrs.

::

Instruction if

Pour utiliser if, placez l'expression conditionnelle entre parenthèses () et les actions à effectuer si le résultat est vrai entre accolades {}.

fun main() {
    val age = 25

    if (age >= 18) {
        println("Vous êtes majeur.")
    } else {
        println("Vous êtes mineur.")
    }
}

Dans cet exemple, on vérifie si la variable age est supérieure ou égale à 18. Si c'est le cas, le message "Vous êtes majeur." est affiché. Sinon, le message "Vous êtes mineur." est affiché.

Opérateur ternaire

Kotlin ne dispose pas d'opérateur ternaire de la forme condition ? then : else. À la place, l'instruction if peut être utilisée comme une expression. Dans ce cas, les accolades {} ne sont pas nécessaires.

fun main() { 
    // Début de l'exemple
    val a = 1
    val b = 2

    println(if (a > b) a else b) // Renvoie une valeur : 2
    // Fin de l'exemple
}

When

Utilisez when pour les expressions conditionnelles à branches multiples Kotlin propose l'instruction when pour gérer les expressions conditionnelles qui ont plusieurs branches possibles. when peut être utilisé comme une instruction ou comme une expression.

when comme instruction

Pour utiliser when comme une instruction, procédez comme suit :

  1. Placez l'expression conditionnelle entre parenthèses ().

  2. Utilisez des accolades {} pour regrouper les actions à effectuer pour chaque branche.

  3. Séparez chaque condition de l'action correspondante à l'aide de la flèche ->.

fun main() {
    // Début de l'exemple
    val obj = "Hello"

    when (obj) {
        // Vérifie si obj est égal à "1"
        "1" -> println("Un")
        // Vérifie si obj est égal à "Hello"
        "Hello" -> println("Salut")
        // Instruction par défaut
        else -> println("Inconnu")     
    }
    // Salut
  // Fin de l'exemple
}

Explication

Dans cet exemple, on utilise when pour vérifier la valeur de la variable obj. On compare obj à plusieurs valeurs possibles ("1" et "Hello").

  1. Si obj est égal à "1", le message "Un" est affiché.

  2. Si obj est égal à "Hello", le message "Salut" est affiché.

  3. Si obj ne correspond à aucune des conditions précédentes, l'instruction else est exécutée et le message "Inconnu" est affiché. Remarque

Dans cet exemple, la branche else est nécessaire car when utilisé comme instruction exige explicitement que toutes les valeurs possibles soient couvertes.

Remarque sur l'évaluation des branches when

Il est important de noter que les conditions des branches when sont évaluées séquentiellement jusqu'à ce que l'une d'elles soit satisfaite. Ainsi, seule la >première branche appropriée est exécutée.

En d'autres termes, when compare la valeur de l'expression conditionnelle à chaque condition de branche, de haut en bas. Dès qu'une condition correspond, le code associé à cette branche est exécuté et l'évaluation s'arrête. Les conditions restantes ne sont pas vérifiées.

when comme expression

En plus de fonctionner comme une instruction, when peut également être utilisé comme une expression. Dans ce cas, when renvoie la valeur de la branche correspondante.

fun main() {
    // Début de l'exemple
    val obj = "Hello"    

    val result = when (obj) {
        // Si obj est égal à "1", définit result à "Un"
        "1" -> "Un"
        // Si obj est égal à "Hello", définit result à "Salut"
        "Hello" -> "Salut"
        // Définit result à "Inconnu" si aucune condition précédente n'est satisfaite
        else -> "Inconnu"
    }
    println(result)
    // Salut
  // Fin de l'exemple   
}

Explication

Dans cet exemple, on utilise when comme une expression pour attribuer la valeur appropriée à la variable result. when compare la valeur de obj aux conditions de chaque branche. Si une condition correspond, la valeur associée à cette branche (par exemple, "Un" ou "Salut") est assignée à result.

Branche else obligatoire

Lorsque when est utilisé comme une expression, la branche else est obligatoire. Cela garantit que l'expression when renvoie toujours une valeur. Cependant, l'exigence de else peut être levée si le compilateur Kotlin peut déterminer de manière concluante que toutes les valeurs possibles sont couvertes par les conditions des branches existantes.

Utilisations de when

L'exemple précédent montrait comment utiliser when pour comparer une variable à différentes valeurs. when peut également être utilisé pour vérifier une chaîne d'expressions booléennes.

when avec des expressions booléennes en chaîne

En plus de comparer des variables à des valeurs spécifiques, when peut également être utilisé pour vérifier une série d'expressions booléennes. Cela permet d'écrire du code plus clair et plus concis, en particulier lorsque vous avez plusieurs conditions imbriquées.

fun main() {
// Début de l'exemple
    val temp = 18

    val description = when {
        // Si temp < 0 est vrai, définit description à "très froid"
        temp < 0 -> "très froid"
        // Si temp < 10 est vrai, définit description à "un peu froid"
        temp < 10 -> "un peu froid"
        // Si temp < 20 est vrai, définit description à "chaud"
        temp < 20 -> "chaud"
        // Définit description à "chaud" si aucune condition précédente n'est satisfaite
        else -> "chaud"             
    }
    println(description)
    // chaud
  // Fin de l'exemple
}

Explication

Dans cet exemple, on utilise when pour catégoriser la température stockée dans la variable temp. On n'utilise pas de variable de condition explicite. À la place, chaque branche de when est une expression booléenne. Si l'expression est vraie, le code associé à cette branche est exécuté et la valeur correspondante (par exemple, "très froid" ou "chaud") est assignée à la variable description.

Intervalles (Ranges)

Avant de parler des boucles, il est utile de savoir comment construire des intervalles pour les boucles afin qu'elles puissent itérer sur des éléments.

La façon la plus courante de créer un intervalle en Kotlin est d'utiliser l'opérateur .. Par exemple, 1..4 est équivalent à 1, 2, 3, 4. Cet intervalle inclut la valeur de début et la valeur de fin.

Pour déclarer un intervalle qui n'inclut pas la valeur de fin, utilisez l'opérateur ..< Par exemple, 1..<4 est équivalent à 1, 2, 3.

Pour déclarer un intervalle dans l'ordre inverse, utilisez downTo. Par exemple, 4 downTo 1 est équivalent à 4, 3, 2, 1.

Pour déclarer un intervalle dont l'incrémentation est différente de 1, utilisez step suivi de la valeur d'incrémentation souhaitée. Par exemple, 1..5 step 2 est équivalent à 1, 3, 5.

Vous pouvez également faire la même chose avec des intervalles de caractères (Char):

  • 'a'..'d' est équivalent à 'a', 'b', 'c', 'd'

  • 'z' downTo 's' step 2 est équivalent à 'z', 'x', 'v', 't'

Boucles

Les deux structures de boucles les plus courantes en programmation sont for et while. Utilisez for pour parcourir une plage de valeurs et effectuer une action. Utilisez while pour répéter une action jusqu'à ce qu'une condition particulière soit remplie.

Boucle For

En utilisant vos nouvelles connaissances sur les intervalles, vous pouvez créer une boucle for qui parcourt les nombres de 1 à 5 et imprime le nombre à chaque fois.

Placez l'itérateur et l'intervalle entre parenthèses () avec le mot-clé in. Ajoutez l'action que vous voulez effectuer à l'intérieur des accolades {}:

fun main() {
//sampleStart
    for (nombre in 1..5) { 
        // nombre est l'itérateur et 1..5 est l'intervalle
        print(nombre)
    }
    // 12345
//sampleEnd
}

Les boucles peuvent également parcourir des collections :

fun main() { 
//sampleStart
    val gâteaux = listOf("carotte", "fromage", "chocolat")

    for (gâteau in gâteaux) {
        println("Miam, c'est un gâteau ${gâteau} !")
    }
    // Miam, c'est un gâteau carotte !
    // Miam, c'est un gâteau fromage !
    // Miam, c'est un gâteau chocolat !
//sampleEnd
}

Dans cet exemple, on utilise la boucle for pour parcourir une liste de gâteaux (gâteaux) et affiche un message pour chaque type de gâteau.

Boucle while

La boucle while peut être utilisée de deux manières :

  • Pour exécuter un bloc de code tant qu'une expression conditionnelle est vraie (while).

  • Pour exécuter d'abord le bloc de code, puis vérifier l'expression conditionnelle (do-while).

Dans le premier cas d'utilisation (while) :

  • Déclarez l'expression conditionnelle pour que votre boucle while continue entre parenthèses ().

  • Ajoutez l'action que vous voulez effectuer à l'intérieur des accolades {}.

Les exemples suivants utilisent l'opérateur d'incrémentation (++) pour incrémenter la valeur de la variable cakesEaten.

fun main() {
//sampleStart
    var cakesEaten = 0
    while (cakesEaten < 3) {
        println("Mange un gâteau") // En français, on utilise "manger"
        cakesEaten++
    }
    // Mange un gâteau
    // Mange un gâteau
    // Mange un gâteau
//sampleEnd
}

Dans le deuxième cas d'utilisation (do-while) :

  • Déclarez l'expression conditionnelle pour que votre boucle continue entre parenthèses ().

  • Définissez l'action que vous voulez effectuer à l'intérieur des accolades {} avec le mot-clé do.

fun main() {
//sampleStart
    var cakesEaten = 0
    var cakesBaked = 0
    while (cakesEaten < 3) {
        println("Eat a cake")
        cakesEaten++
    }
    do {
        println("Bake a cake")
        cakesBaked++
    } while (cakesBaked < cakesEaten)
    // Eat a cake
    // Eat a cake
    // Eat a cake
    // Bake a cake
    // Bake a cake
    // Bake a cake
//sampleEnd
}

Pratique

Mission 4

En se basant sur la mission précédente, nous souhaitons améliorer notre application.

En tant que développeur, votre mission est de:

  1. Afficher tous les événements disponibles.

  2. Afficher toutes les catégories disponibles.

Correction Mission 3

Vous disposez d'un ensemble de protocoles pris en charge par votre serveur. Un utilisateur demande à utiliser un protocole particulier. Complétez le programme pour vérifier si le protocole demandé est pris en charge ou non (isSupported doit être une valeur booléenne).

fun main() {
    val SUPPORTED = setOf("HTTP", "HTTPS", "FTP")
    val requested = "smtp"
    val isSupported = requested.uppercase() in SUPPORTED
    println("Support for $requested: $isSupported")
}

Les fonctions

Tshaba était un développeur talentueux, mais il avait une mauvaise habitude : il n'utilisait jamais de fonctions dans son code. A la place, il répétait inlassablement les mêmes instructions, ce qui rendait son code long, illisible et difficile à maintenir.

Un jour, Tshaba travaillait sur un projet particulièrement complexe. Il devait écrire du code pour gérer une liste d'utilisateurs et leurs informations. Le code devenait de plus en plus long et difficile à suivre. Tshaba savait qu'il devait trouver une solution pour le simplifier.

C'est alors qu'un collègue lui parla des fonctions. Il lui expliqua comment les fonctions pouvaient être utilisées pour regrouper des blocs de code et les réutiliser plusieurs fois. Tshaba était intrigué. Il avait toujours pensé que les fonctions étaient trop compliquées pour lui.

Mais il décida de donner une chance aux fonctions. Il commença à lire des tutoriels et à expérimenter. Au début, c'était difficile. Il ne comprenait pas bien comment les utiliser et il faisait souvent des erreurs. Mais il persévéra et, petit à petit, il commença à comprendre.

En français, vous pouvez définir vos propres fonctions en Kotlin à l'aide du mot-clé fun.

fun bonjour() {
  println("Bonjour, le monde !")
}

fun main() {
  bonjour()
  // Bonjour, le monde !
}

En kotlin :

  • Les paramètres de fonction sont écrits entre parenthèses ().

  • Chaque paramètre doit avoir un type, et les paramètres multiples doivent être séparés par des virgules ,.

  • Le type de retour est écrit après les parenthèses de la fonction (), séparé par deux points :.

  • Le corps d'une fonction est écrit entre des accolades {}.

  • Le mot-clé return est utilisé pour quitter ou retourner quelque chose d'une fonction.

Si une fonction ne renvoie rien d'utile, le type de retour et le mot-clé return peuvent être omis.

Dans l'exemple suivant :

  • x et y sont des paramètres de fonction.

  • x et y ont le type Int.

  • Le type de retour de la fonction est Int.

  • La fonction renvoie la somme de x et y lorsqu'elle est appelée.

fun sum(x: Int, y: Int): Int {
    return x + y
}

fun main() {
    println(sum(1, 2))
    // 3
}

En Kotlin, nous recommandons de nommer les fonctions en utilisant la casse mixte en commençant par une lettre minuscule. Par exemple, utilisez printMessageWithPrefix au lieu de print_message_with_prefix.

Arguments nommés

En Kotlin, vous pouvez appeler des fonctions avec ou sans inclure les noms des paramètres. L'inclusion des noms de paramètres améliore la lisibilité du code, en particulier lorsque les fonctions ont plusieurs paramètres.

Avec les arguments nommés, vous pouvez spécifier le nom du paramètre et sa valeur correspondante, ce qui vous permet de réorganiser les arguments lors de l'appel de la fonction.

fun printMessageWithPrefix(message: String, prefix: String) {
  println("[$prefix] $message")
}

fun main() {
  // Utilise des arguments nommés avec un ordre d'arguments inversé
  printMessageWithPrefix(prefix = "Log", message = "Bonjour")
  // [Log] Bonjour
}

Valeurs de paramètres par défaut en Kotlin

Vous pouvez définir des valeurs par défaut pour les paramètres de vos fonctions. Tout paramètre ayant une valeur par défaut peut être omis lors de l'appel de la fonction. Pour déclarer une valeur par défaut, utilisez l'opérateur d'affectation = après le type :

fun printMessageWithPrefix(message: String, prefix: String = "Info") {
    println("[$prefix] $message")
}

fun main() {
    // Fonction appelée avec les deux paramètres
    printMessageWithPrefix("Bonjour", "Log") 
    // [Log] Bonjour

    // Fonction appelée uniquement avec le paramètre message
    printMessageWithPrefix("Bonjour")        
    // [Info] Bonjour

    printMessageWithPrefix(prefix = "Log", message = "Bonjour")
    // [Log] Bonjour
}
  • Fonction printMessageWithPrefix:

    Prend deux paramètres : message (de type String) et prefix (avec une valeur par défaut "Info" de type String). Affichier le message entre crochets avec le préfixe en utilisant println.

Vous pouvez ignorer des paramètres spécifiques avec des valeurs par défaut, sans avoir à les omettre tous. Cependant, après le premier paramètre ignoré, vous devez nommer tous les paramètres suivants.

Fonctions sans valeur de retour

Si votre fonction ne renvoie pas de valeur utile, son type de retour est Unit. Unit est un type particulier en Kotlin qui ne possède qu'une seule valeur possible, également nommée Unit.

En conséquence, il n'est pas nécessaire de déclarer explicitement que Unit est retourné dans le corps de la fonction. Cela signifie que vous pouvez omettre le mot-clé return et le type de retour :

fun printMessage(message: String) {
    println(message)
    // `return Unit` ou `return` est optionnel
}

fun main() {
    printMessage("Bonjour")
    // Bonjour
}

Fonctions à expression unique

Pour rendre votre code plus concis, vous pouvez utiliser des fonctions à expression unique. Par exemple, la fonction sum() peut être raccourcie :

fun sum(x: Int, y: Int): Int {
    return x + y
}

fun main() {
    println(sum(1, 2))
    // 3
}

En Kotlin, vous pouvez supprimer les accolades {} et définir le corps de la fonction en utilisant l'opérateur d'affectation =. De plus, grâce à l'inférence de type de Kotlin, vous pouvez également omettre le type de retour. La fonction sum() devient alors une ligne :

fun sum(x: Int, y: Int) = x + y

fun main() {
    println(sum(1, 2))
    // 3
}

Points clés à retenir :

  • Les fonctions à expression unique permettent d'écrire du code plus concis pour les fonctions simples qui ne nécessitent qu'une seule expression pour effectuer une opération et renvoyer une valeur.

  • Pour utiliser une fonction à expression unique, supprimez les accolades {} et utilisez l'opérateur d'affectation = pour définir le corps de la fonction.

  • L'inférence de type de Kotlin permet d'omettre le type de retour, car le compilateur peut le déduire à partir de l'expression de la fonction. Il est important de noter que l'omission du type de retour n'est possible que lorsque la fonction n'a pas de corps ({}). Cette restriction ne s'applique pas aux fonctions de type Unit qui n'ont pas besoin de renvoyer de valeur et ne requièrent donc pas d'expression explicite.

Pratique

Mission 5

Vous avez une fonction qui convertit un intervalle de temps donné en heures, minutes et secondes en un nombre total de secondes. Dans la plupart des cas, vous n'avez besoin de passer qu'un ou deux paramètres à la fonction, les autres paramètres étant égaux à 0. Améliorez la fonction et le code qui l'appelle en utilisant des valeurs de paramètres par défaut et des arguments nommés pour améliorer la lisibilité du code.

fun intervalInSeconds(hours: Int, minutes: Int, seconds: Int) =
    ((hours * 60) + minutes) * 60 + seconds

fun main() {
    println(intervalInSeconds(1, 20, 15))
    println(intervalInSeconds(0, 1, 25))
    println(intervalInSeconds(2, 0, 0))
    println(intervalInSeconds(0, 10, 0))
    println(intervalInSeconds(1, 0, 1))
}

Correction Mission 5

fun intervalInSeconds(hours: Int = 0, minutes: Int = 0, seconds: Int = 0) =
    ((hours * 60) + minutes) * 60 + seconds

fun main() {
    println(intervalInSeconds(1, 20, 15))
    println(intervalInSeconds(minutes = 1, seconds = 25))
    println(intervalInSeconds(hours = 2))
    println(intervalInSeconds(minutes = 10))
    println(intervalInSeconds(hours = 1, seconds = 1))
}

Expressions Lambda

Kotlin vous permet d'écrire du code encore plus concis pour les fonctions en utilisant des expressions lambda.

Par exemple, la fonction uppercaseString() suivante :

fun uppercaseString(string: String): String {
    return string.uppercase()
}

fun main() {
    println(uppercaseString("bonjour"))
    // BONJOUR
}

Peut également être écrite sous forme d'expression lambda :

fun main() {
    println({ string: String -> string.uppercase() }("bonjour"))
    // BONJOUR
}

Les expressions lambda peuvent être difficiles à comprendre au premier abord, alors décortiquons-les. Les expressions lambda sont écrites entre des accolades {}.

  • { ... } : Les accolades délimitent le corps de l'expression lambda.

  • string: String : Ceci définit un paramètre nommé string de type String pour la lambda.

  • -> : La flèche sépare les paramètres du corps de la lambda.

  • string.uppercase() : Ceci est le corps de la lambda, qui convertit la chaîne string en majuscules en utilisant la fonction uppercase().

  • ("bonjour") : C'est l'argument passé à la lambda lors de son exécution. Ici, on lui transmet la chaîne "bonjour".

  • string : C'est le paramètre unique de la lambda, nommé pour plus de clarté.

  • String : Il s'agit du type de ce paramètre, indiquant qu'il attend une chaîne de caractères en entrée.

  • L'expression lambda renvoie le résultat de la fonction uppercase() appliquée au paramètre string.

  • La fonction uppercase() convertit une chaîne de caractères en majuscules.

-> est facultative. L'exemple illustre un lambda simple qui imprime un message sur la console :

{ println("Message de journal") }