En Kotlin, il existe deux approches différentes pour l'initialisation tardive des propriétés : lateinit et lazy.
lateinit — un modificateur appliqué aux variables (var) qui seront initialisées plus tard, généralement via DI ou dans un bloc d'initialisation. Convient uniquement aux variables non statiques de types NON nullable. L'accès avant l'initialisation lance une exception UninitializedPropertyAccessException.
class MyClass { lateinit var data: String fun init() { data = "Hello!" } }
lazy — un délégué spécial appliqué aux propriétés val (uniquement en lecture). L'expression d'initialisation est évaluée lors de la première utilisation de la variable. Sûr pour un accès multithreading par défaut.
val config: Config by lazy { loadConfigFromFile() }
lateinit ne fonctionne pas avec des types primitifs et val.lazy ne permet pas la réinitialisation.lateinit — pour les variables qui seront certainement assignées plus tard (par exemple, via un framework DI ou dans un fragment du cycle de vie Android).lazy — pour les calculs paresseux, lorsque la valeur est coûteuse à calculer et peut ne pas être demandée.Peut-on utiliser
lateinitpour des propriétés de type Int ?
Réponse : Non. lateinit ne fonctionne qu'avec des types objet NON nullable. Pas pour les primitifs et les types nullable - c'est impossible. Tenter de déclarer lateinit var a: Int entraînera une erreur de compilation.
Histoire
Dans un projet éducatif, ils ont déclaré une variable de configuration comme lateinit var config: Config?, mais le compilateur n'a pas permis de le faire — ils ont gagné du temps, mais ont dû comprendre pourquoi cela ne fonctionnait pas comme prévu.
Histoire
Dans une application Android, ils ont oublié de vérifier l'initialisation de la propriété lateinit avant l'appel. Cela a conduit à un crash de l'application en production — le designer a tenté d'accéder à la propriété avant onCreateView. Des vérifications supplémentaires ont aidé.
Histoire
Lors de l'utilisation du multithreading, un développeur a utilisé by lazy pour initialiser un objet consommant des ressources sans passer de paramètre, pensant que le délégué par défaut n'était pas thread-safe. Au final, des problèmes de condition de course sont apparus dans la version. Ils ont résolu cela en passant le paramètre approprié pour lazy : by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { ... }.