Pouvez-vous expliquer le principe de fonctionnement d'un délégué dans une classe en Kotlin?
sobes.tech IA
Réponse de l'IA
Un délégué en Kotlin est un objet qui assume l'exécution d'une tâche spécifique ou délègue des appels de méthodes à un autre objet.
Scénarios principaux d'utilisation:
-
Délégation de propriétés: Transférer le contrôle des getters et setters d'une propriété à un autre objet.
lazy: Évaluation de la valeur de la propriété lors de la première accès.observable: Exécuter une action lorsque la valeur de la propriété change.vetoable: Empêcher le changement de la valeur de la propriété basé sur une condition.
class Example { // Calculé uniquement lors du premier accès val lazyValue: String by lazy { println("Calcul!") "Bonjour" } // Appelé à chaque changement de valeur var name: String by Delegates.observable("<pas de nom>") { prop, old, new -> println("Le nom a changé de $old à $new") } } -
Délégation d'interfaces: Implémentation d'une interface en redirigeant les appels de méthodes vers un autre objet.
interface Base { fun print() } class BaseImpl(val x: Int) : Base { override fun print() { println(x) } } // Implémente Base, déléguant les appels à BaseImpl class Derived(b: Base) : Base by b fun main() { val b = BaseImpl(10) Derived(b).print() // Affiche 10 } -
Délégation de fonctions: Bien qu'il n'existe pas de syntaxe explicite pour déléguer des fonctions individuelles comme pour les propriétés ou interfaces, cela se réalise conceptuellement par composition et appel de méthodes d'un autre objet.
Comment fonctionne la délégation de propriétés:
Le compilateur Kotlin génère du code auxiliaire. Pour une propriété déléguée à un objet delegate, le compilateur génère une propriété cachée et appelle les méthodes getValue et setValue (pour les propriétés modifiables) sur l'objet delegate, en passant le contexte nécessaire (instance de la classe, métadonnées de la propriété).
// Exemple de pseudocode, comment le compilateur traite : val p: String by delegate
/*
private val _p: Delegate<Any?, String> = delegate_initializer
val p: String
get() = _p.getValue(this, ::p) // Appel à getValue sur le délégué
*/
L'objet délégué doit avoir les méthodes correspondantes:
getValue(thisRef, property: KProperty<*>): Tpour une propriété de typeT.thisRefest l'instance de la classe,propertysont les métadonnées de la propriété.setValue(thisRef, property: KProperty<*>, value: T)pour une propriété modifiable.
Avantages de l'utilisation des délégués:
- Réutilisation du code: La logique commune (initialisation paresseuse, observation des changements) est extraite dans un délégué séparé et réutilisée.
- Amélioration de la lisibilité: Le code devient moins verbeux, le code boilerplate est caché dans le délégué.
- Modularité: La logique de gestion des propriétés ou d'implémentation d'interfaces est séparée de la logique principale de la classe.