Contactez-nous

`val` vs `var` : le principe d'immutabilité

Explorez la différence fondamentale entre `val` (immutable) et `var` (mutable) en Kotlin. Découvrez pourquoi privilégier l'immutabilité pour un code plus sûr.

Déclarer des variables : les deux mots-clés essentiels

En Kotlin, lorsque vous souhaitez stocker une valeur pour l'utiliser plus tard dans votre programme, vous devez la déclarer à l'aide d'un nom : c'est ce qu'on appelle une variable. Contrairement à certains langages qui n'ont qu'un seul mot-clé pour cela, Kotlin en propose deux distincts : `val` et `var`. Ce choix n'est pas anodin ; il introduit dès le départ une distinction fondamentale liée à la mutabilité de la *référence* de la variable, un concept clé pour écrire du code robuste et prévisible.

Comprendre la différence entre `val` et `var` est l'une des premières étapes cruciales dans l'apprentissage de Kotlin. Cela influence directement la manière dont vous concevez et écrivez votre code, en vous incitant à réfléchir à la nécessité ou non de modifier une valeur après sa première assignation. Cette distinction est au coeur du principe d'immutabilité que Kotlin encourage fortement.

`val` : la référence immuable (Read-only)

Le mot-clé `val` vient de "value" (valeur). Lorsque vous déclarez une variable avec `val`, vous créez une référence immuable ou lecture seule (read-only). Cela signifie qu'une fois que vous avez assigné une valeur initiale à une variable `val`, vous ne pouvez plus jamais la réassigner pour qu'elle pointe vers une autre valeur ou un autre objet.

Pensez à `val` comme à une constante en termes de référence. La variable est initialisée une seule fois et conserve cette référence pour toute sa durée de vie.

fun main() {
    // Déclaration avec val
    val question = "La grande question sur la vie, l'univers et le reste"
    val answer = 42
    val pi = 3.14159

    println(question) // Affiche la question
    println("La réponse est: $answer") // Affiche 42

    // Tentative de réassignation (va provoquer une erreur de compilation !)
    // answer = 43 // Erreur: Val cannot be reassigned
    // pi = 3.14 // Erreur: Val cannot be reassigned
}

L'erreur de compilation générée si vous tentez de réassigner une `val` est une protection puissante. Elle garantit que la valeur associée à ce nom ne changera pas de manière inattendue ailleurs dans votre code.

Attention à la nuance : `val` garantit l'immutabilité de la référence, pas nécessairement de l'objet lui-même. Si la `val` référence un objet mutable (comme une liste mutable), vous pouvez toujours modifier l'état interne de cet objet. Cependant, la variable `val` pointera toujours vers la *même instance* de l'objet.
import java.util.ArrayList // ArrayList est mutable

fun main() {
    val mutableList = ArrayList()
    // Alternative Kotlin: val mutableList = mutableListOf()

    mutableList.add("Apple") // OK: On modifie l'objet interne
    mutableList.add("Banana") // OK: On modifie toujours le même objet

    println(mutableList) // Affiche [Apple, Banana]

    // Tentative de réassignation (Erreur !)
    // mutableList = ArrayList() // Erreur: Val cannot be reassigned
    // Même si on essaie de l'assigner à une nouvelle liste vide, c'est interdit.
}

`var` : la référence mutable (Mutable)

Le mot-clé `var` vient de "variable". Lorsque vous déclarez une variable avec `var`, vous créez une référence mutable. Cela signifie que vous pouvez non seulement lui assigner une valeur initiale, mais aussi la réassigner ultérieurement pour qu'elle pointe vers une nouvelle valeur ou un nouvel objet (compatible en type).

Utilisez `var` lorsque vous savez que la valeur associée à ce nom devra changer au cours de l'exécution de votre programme.

fun main() {
    // Déclaration avec var
    var counter = 0
    println("Compteur initial: $counter") // Affiche 0

    counter = counter + 1 // Réassignation: OK
    println("Compteur après incrément: $counter") // Affiche 1

    counter += 5 // Autre forme de réassignation: OK
    println("Compteur après ajout: $counter") // Affiche 6

    var userName = "Alice"
    println("Utilisateur: $userName") // Affiche Alice

    userName = "Bob" // Réassignation: OK
    println("Utilisateur changé: $userName") // Affiche Bob
}

Les variables `var` offrent plus de flexibilité car leur valeur peut évoluer. Cependant, cette flexibilité a un coût : il peut être plus difficile de suivre l'état d'une variable `var` dans des programmes complexes, surtout si elle est modifiée à plusieurs endroits ou dans des contextes concurrents (multi-threading).

Le principe d'immutabilité et la bonne pratique Kotlin

Kotlin encourage fortement l'utilisation de l'immutabilité autant que possible. Cela signifie qu'il faut préférer `val` à `var` par défaut. N'utilisez `var` que lorsque la mutabilité est absolument nécessaire pour la logique de votre algorithme (par exemple, pour un compteur, accumuler un résultat dans une boucle, ou stocker un état qui change explicitement).

Pourquoi cette préférence pour `val` et l'immutabilité ?

  • Prévisibilité et raisonnement : Le code utilisant principalement `val` est plus facile à comprendre et à raisonner. Quand vous lisez une variable `val`, vous savez que sa référence ne changera jamais après son initialisation. Cela simplifie le suivi du flux de données.
  • Sécurité (Thread Safety) : Les objets et références immuables sont intrinsèquement plus sûrs à utiliser dans des environnements multi-threadés. Comme leur état ou leur référence ne peut pas changer, il n'y a pas de risque de conditions de concurrence (race conditions) liées à des modifications inattendues par différents threads.
  • Moins d'effets de bord : L'immutabilité aide à réduire les effets de bord indésirables, où une modification dans une partie du code affecte de manière inattendue une autre partie qui utilise la même variable mutable.
  • Alignement avec la programmation fonctionnelle : L'immutabilité est un pilier de la programmation fonctionnelle, un paradigme que Kotlin supporte et encourage.

Adopter l'habitude de déclarer systématiquement avec `val` et de ne passer à `var` qu'en cas de besoin réel est une des bonnes pratiques fondamentales en Kotlin. Cela conduit à un code plus sûr, plus lisible et plus facile à maintenir sur le long terme.

En résumé : `val` vs `var`

La distinction est simple mais fondamentale :

  • Utilisez `val` pour les variables dont la référence ne changera pas après l'initialisation (lecture seule). C'est le choix par défaut recommandé.
  • Utilisez `var` pour les variables dont la référence peut être modifiée après l'initialisation. A utiliser uniquement lorsque la mutabilité est nécessaire.

Cette distinction claire, imposée par le langage dès la déclaration, est une aide précieuse pour construire des applications Kotlin robustes et maintenables en favorisant l'immutabilité.