lazy et lateinit
Fait partie de la section Programmation orientée objet du Journey Kotlin de Coddy. Leçon 10 sur 57.
by lazy { ... } retarde le calcul d'une val jusqu'à sa première lecture, puis mémorise le résultat. Cela convient aux valeurs dont le calcul est coûteux ou qui ne sont pas toujours nécessaires :
class Report(val rows: List<Int>) {
val summary: String by lazy {
println("computing summary")
"total ${rows.sum()}"
}
}À l'intérieur de main :
val r = Report(listOf(3, 4))
println("created")
println(r.summary)
println(r.summary)Sortie :
created
computing summary
total 7
total 7Le bloc s’exécute une seule fois : la deuxième lecture ci-dessus a utilisé le résultat stocké. Contrairement à un getter personnalisé, qui s’exécute à chaque lecture, lazy calcule une fois et met le résultat en cache :
class Demo {
var reads = 0
val viaGetter: Int
get() { reads++; return 42 }
val viaLazy: Int by lazy { reads++; 42 }
}À l’intérieur de main :
val d = Demo()
repeat(3) { d.viaGetter; d.viaLazy }
println(d.reads)Sortie :
4lateinit var déclare une propriété non nulle qui est assignée ultérieurement, après la construction, par exemple par une méthode de configuration. La lire avant qu’elle ne soit assignée déclenche une exception, et ::name.isInitialized permet de la vérifier :
class Screen {
lateinit var title: String
fun load(t: String) { title = t }
fun ready() = ::title.isInitialized
}Dans main :
val s = Screen()
println(s.ready())
s.load("Home")
println(s.ready())
println(s.title)Sortie :
false
true
HomePrivilégiez l'initialisation directe lorsque la valeur est connue lors de la construction. Utilisez lazy pour un val coûteux qui pourrait ne pas être nécessaire, et lateinit uniquement pour un var dont la valeur arrive réellement plus tard ; lateinit ne fonctionne pas avec Int, Boolean ni les autres types primitifs.
val config by lazy { loadConfig() } // calculé à la première utilisation, une seule fois
lateinit var user: User // assigné après la construction
// lateinit var count: Int // erreur : non autorisé sur les types primitifsDéfi
FacileComplétez la classe Document(val text: String). Ajoutez wordCount en tant que propriété lazy qui compte les mots (séparés par des espaces simples) et enregistre chaque calcul en ajoutant 1 à computations, ainsi qu’un lateinit var author: String avec une méthode credit() qui renvoie by Ada ou by unknown lorsque l’auteur n’a pas été défini.
Le code fourni lit le texte, lit wordCount trois fois, définit l’auteur lorsqu’une deuxième ligne est présente et affiche words 5, computed 1, by Ada.
Votre code doit être placé dans Document.kt. Main.kt contient le code fourni d’entrée/sortie et ne peut pas être modifié.
Essayez vous-même
fun main() {
// Code d'entrée/sortie fourni : le garder tel quel
val input = generateSequence(::readLine).toList()
val doc = Document(input[0])
val reads = List(3) { doc.wordCount }
val words = reads.first()
if (input.size > 1) doc.author = input[1]
println("words $words, computed ${doc.computations}, ${doc.credit()}")
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation orientée objet
1Classes et objets
Travailler avec des fichiersDéfinir des classesConstructeurs primairesBlocs init et validationConstructeurs secondairesRécapitulatif - Carte de bibliothèque4Héritage
Classes ouvertes et sous-classesRedéfinition des membressuper et constructeursClasses abstraitesRécapitulatif – Annuaire du personnel2Propriétés et encapsulation
Accesseurs personnalisésModificateurs de visibilitéSetters privéslazy et lateinitRécapitulatif - Compte bancaire5Interfaces
Déclarer des interfacesMéthodes par défautInterfaces multiplesInterfaces en tant que typesRécapitulatif - Méthodes de paiement8Génériques
Fonctions génériquesClasses génériquesContraintes de typeVariance avec in et outRécapitulatif - File de priorité11Projet : Gestion de bibliothèque
Livres et membresEmprunter des livresEntraînez-vous par vous-même : Playground Kotlin