ProgrammationDéveloppeur Kotlin intermédiaire

Comment la délégation de propriétés est-elle mise en œuvre en Kotlin ? Décrivez les mécanismes, les avantages, les limites et fournissez un exemple détaillé.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

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 :

  • Logique de possession des données réutilisable
  • Mise en œuvre facile de modèles tels que l'initialisation paresseuse, le caching, le contrôle d'accès, la journalisation, etc.
  • Code plus propre et déclaratif

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 :

  • La délégation ne fonctionne qu'avec les propriétés de classe (pas avec des variables/propriétés de niveau supérieur dans des objets)
  • Problèmes potentiels avec la sérialisation (si le délégué contient des champs non sérialisables)

Question piège

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.

Exemples d’erreurs réelles dues à la méconnaissance des subtilités du sujet


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.