En Kotlin, il existe une prise en charge intégrée des propriétés déléguées (delegated properties). Le mécanisme by permet de déléguer le getter/setter de n'importe quelle propriété à un objet spécialisé — le délégué. Les délégués les plus connus sont : lazy, observable, vetoable et des délégués personnalisés.
Avantages :
Exemple de délégué personnalisé :
class UpperCaseDelegate { private var value: String = "" operator fun getValue(thisRef: Any?, property: KProperty<*>): String = value operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: String) { value = newValue.uppercase() } } class Person { var name: String by UpperCaseDelegate() }
Limites :
Peut-on utiliser un délégué nécessitant un accès au contexte (par exemple, Android Context), dans des propriétés d'objets compagnons ou d'objets de niveau supérieur ?
Deux réponses incorrectes reviennent souvent : "on peut toujours, pourquoi pas ?"
Réponse correcte : Non, car les objets compagnons et les objets de niveau supérieur sont initialisés avant les instances de classe ou d'application, ce qui peut entraîner des erreurs liées à l'accès à un contexte non initialisé. Les délégués nécessitant un accès à l'instance ne doivent être utilisés que dans les propriétés de la classe.
Histoire
Délégation d'initialisation paresseuse dans Android-ViewModel : Un programmeur a placé un délégué heavy-lazy dans l'objet compagnon. Dans certaines situations (après la mise à jour du SDK), l'application a commencé à planter lors de l'initialisation — le contexte n'était pas encore accessible, mais le délégué avait déjà exécuté son "init".
Histoire
Sérialisation incorrecte avec des délégués : Un délégué personnalisé a été utilisé pour stocker des données, mais contenait des références non sérialisables au contexte. Lors de la tentative de sérialisation, des erreurs et une perte de données se sont produites.
Histoire
Délégué observable avec un rappel incorrect : Un développeur a utilisé Delegates.observable pour contrôler l'état, et à l'intérieur de la lambda, une nouvelle valeur était assignée, ce qui a entraîné une boucle infinie et un StackOverflowError à l'exécution.