0Pricing
Scala for Backend Engineering & Functional Programming · Leçon

Fermetures

Capturez l’état

Fermetures est une leçon Scala for Backend Engineering & Functional Programming gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Scala for Backend Engineering & Functional Programming, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Scala for Backend Engineering & Functional Programming comprend 4 leçons au total.

Qu’est-ce qu’une fermeture ?

Une fermeture est une fonction qui capture des variables dans la portée environnante où elle a été définie. Elle « capture » ces variables et conserve l’accès à celles-ci, même après la fin de cette portée.

object Main {
  def main(args: Array[String]): Unit = {
    val factor = 3
    val multiply = (x: Int) => x * factor
    println(multiply(5))
  }
}

Capturer une variable libre

Dans x => x * factor, x est un paramètre, tandis que factor est une variable libre provenant de la portée englobante. La fonction conserve une référence vers celle-ci.

object Main {
  def main(args: Array[String]): Unit = {
    val greeting = "Hello"
    val greet = (name: String) => s"$greeting, $name!"
    println(greet("Ann"))
    println(greet("Bob"))
  }
}

Les fermetures survivent à leur portée

Lorsqu’une fonction renvoie une fermeture, les variables capturées restent accessibles aussi longtemps que la fermeture, même si la fonction qui l’a définie est déjà terminée.

object Main {
  def makeAdder(n: Int): Int => Int = x => x + n
  def main(args: Array[String]): Unit = {
    val add10 = makeAdder(10)
    val add100 = makeAdder(100)
    println(add10(5))
    println(add100(5))
  }
}

Chaque fermeture possède sa propre capture

Appeler deux fois une fabrique de fonctions produit deux fermetures indépendantes, chacune conservant sa propre valeur capturée.

object Main {
  def prefixer(p: String): String => String = s => p + s
  def main(args: Array[String]): Unit = {
    val withDr = prefixer("Dr. ")
    val withMr = prefixer("Mr. ")
    println(withDr("Smith"))
    println(withMr("Jones"))
  }
}

Capturer un état mutable

Une fermeture peut capturer un var, le lire et le mettre à jour. Cela permet à une fermeture de conserver un état entre les appels, comme un compteur.

object Main {
  def main(args: Array[String]): Unit = {
    var count = 0
    val increment = () => { count += 1; count }
    println(increment())
    println(increment())
    println(increment())
  }
}

Une fabrique de compteurs

Combinez ces idées : une fonction qui renvoie une fermeture capturant son propre var privé vous fournit un compteur encapsulé et indépendant.

object Main {
  def counter(): () => Int = {
    var n = 0
    () => { n += 1; n }
  }
  def main(args: Array[String]): Unit = {
    val c1 = counter()
    val c2 = counter()
    println(c1())
    println(c1())
    println(c2())
  }
}

Les fermetures capturent des références, pas des copies

Une fermeture capture la variable, et non un instantané. Si le var capturé est modifié après la création de la fermeture, celle-ci voit la nouvelle valeur.

object Main {
  def main(args: Array[String]): Unit = {
    var msg = "first"
    val show = () => println(msg)
    show()
    msg = "second"
    show()
  }
}

Privilégier la capture d’un val

Capturer un val immuable évite les surprises : la valeur capturée ne change jamais, et la fermeture se comporte donc de manière prévisible. Dans le code fonctionnel, privilégiez la capture de val.

object Main {
  def main(args: Array[String]): Unit = {
    val taxRate = 0.2
    val withTax = (price: Double) => price * (1 + taxRate)
    println(withTax(100))
  }
}

Fermetures et méthodes des collections

Les lambdas transmises à map, filter, etc. sont des fermetures dès qu’elles font référence à des variables externes. C’est extrêmement courant en Scala au quotidien.

object Main {
  def main(args: Array[String]): Unit = {
    val threshold = 3
    val nums = List(1, 2, 3, 4, 5)
    val big = nums.filter(_ > threshold)
    println(big)
  }
}

Un piège de capture dans les boucles

En Scala, la variable d’une boucle for est une nouvelle liaison à chaque itération ; les fermetures capturent donc des valeurs distinctes. Cela évite un bogue classique présent dans certains autres langages.

object Main {
  def main(args: Array[String]): Unit = {
    val fns = for (i <- 1 to 3) yield () => i
    println(fns.map(f => f()))
  }
}

Les fermetures encapsulent comportement et données

Une fermeture regroupe un comportement (le corps de la fonction) et des données (les variables capturées). C'est une alternative légère à un petit objet doté d'une seule méthode.

object Main {
  def discounter(rate: Double): Double => Double = price => price * (1 - rate)
  def main(args: Array[String]): Unit = {
    val sale = discounter(0.25)
    println(sale(80))
    println(sale(200))
  }
}

Vérification rapide

Que capture une fermeture dans la portée qui l'entoure ?

Récapitulatif

Vous avez découvert les fermetures :

  • Une fermeture capture les variables libres de sa portée englobante
  • Les variables capturées vivent plus longtemps que la fonction qui les définit
  • Chaque instance de fermeture possède son propre état capturé
  • Les fermetures capturent des références, donc les captures mutables peuvent changer
  • Les lambdas passées à map/filter sont des fermetures utilisées au quotidien

Questions Fréquemment Posées

La leçon « Fermetures » est-elle gratuite ?

Oui — le texte complet de « Fermetures » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Scala for Backend Engineering & Functional Programming, passe à CoddyKit PRO. Le cours Scala for Backend Engineering & Functional Programming comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Fermetures » ?

Capturez l’état Tu pratiques Scala for Backend Engineering & Functional Programming avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Scala for Backend Engineering & Functional Programming ?

Aucune expérience préalable n'est requise. Scala for Backend Engineering & Functional Programming sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.

Combien de temps prend la leçon « Fermetures » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Scala for Backend Engineering & Functional Programming ?

Oui. Chaque leçon Scala for Backend Engineering & Functional Programming inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Fonctions comme valeurs
  2. Curryfication
  3. Composition
  4. Fermetures
← Retour à Scala for Backend Engineering & Functional Programming