Kotlin Academy · Leçon

Délégués pour les préférences, les propriétés fondées sur une map et la journalisation

Appliquez des délégués à SharedPreferences, au stockage par map et à la journalisation d’audit.

Leçon 4 sur 413 étapes

Délégués pour les préférences, les propriétés fondées sur une map et la journalisation est une leçon Kotlin Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Kotlin Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Kotlin Academy comprend 4 leçons au total.

Propriétés adossées à une table associative

Kotlin permet de déléguer directement des propriétés à une Map. La lecture de la propriété recherche son nom dans la table associative.

class User(map: Map<String, Any?>) {
    val name: String by map
    val age: Int by map
}
fun main() {
    val u = User(mapOf("name" to "Alice", "age" to 30))
    println(u.name) // Alice
    println(u.age)  // 30
}

Délégué MutableMap

Pour les propriétés modifiables, déléguez à une MutableMap : les modifications mettent à jour la table associative sous-jacente.

class Settings(private val map: MutableMap<String, Any?> = mutableMapOf()) {
    var theme: String by map
    var fontSize: Int by map
}
fun main() {
    val s = Settings()
    s.theme = "dark"
    s.fontSize = 16
    println(s.theme)    // dark
    println(s.fontSize) // 16
}

Désérialisation JSON avec un délégué de table associative

Analysez une table associative semblable à du JSON et exposez ses champs sous forme de propriétés typées grâce à la délégation vers une table associative — une solution idéale pour les données dynamiques.

class ApiResponse(data: Map<String, Any?>) {
    val id: Int by data
    val title: String by data
    val published: Boolean by data
}
fun main() {
    val response = ApiResponse(mapOf("id" to 1, "title" to "Kotlin Rocks", "published" to true))
    println(response.title)     // Kotlin Rocks
    println(response.published) // true
}

Schéma de délégué avec journalisation

Enveloppez n’importe quel délégué dans une journalisation afin de suivre de manière transparente chaque lecture et chaque écriture pour toutes les propriétés déléguées.

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
class Logged<T>(private var v: T) : ReadWriteProperty<Any?, T> {
    override fun getValue(t: Any?, p: KProperty<*>): T {
        println("[READ]  ${p.name} = $v"); return v
    }
    override fun setValue(t: Any?, p: KProperty<*>, value: T) {
        println("[WRITE] ${p.name}: $v -> $value"); v = value
    }
}
var config: String by Logged("default")
fun main() { println(config); config = "production" }

Combinaison d’une table associative et de la journalisation

Ajoutez une enveloppe de journalisation autour de la délégation vers une table associative afin d’assurer une traçabilité complète des accès aux propriétés dynamiques.

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
class TrackedMap(private val map: MutableMap<String,Any?> = mutableMapOf()) {
    inner class Delegate<T> : ReadWriteProperty<Any?,T> {
        @Suppress("UNCHECKED_CAST")
        override fun getValue(t:Any?,p:KProperty<*>): T {
            val v = map[p.name] as T; println("read ${p.name}=$v"); return v
        }
        override fun setValue(t:Any?,p:KProperty<*>,value:T) {
            println("write ${p.name}=$value"); map[p.name]=value
        }
    }
    var host: String by Delegate()
}
fun main() { val m=TrackedMap(); m.host="localhost"; println(m.host) }

Délégué de style SharedPreferences

Un délégué qui stocke les valeurs dans une table associative simulant SharedPreferences — adaptez-le aux préférences Android réelles en remplaçant la table associative par des appels aux préférences réelles.

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
val prefs = mutableMapOf<String, Any?>()
fun <T> pref(default: T): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> {
    @Suppress("UNCHECKED_CAST")
    override fun getValue(t: Any?, p: KProperty<*>): T = prefs.getOrDefault(p.name, default) as T
    override fun setValue(t: Any?, p: KProperty<*>, value: T) { prefs[p.name] = value }
}
object UserPrefs {
    var username: String by pref("Guest")
    var isDarkMode: Boolean by pref(false)
}
fun main() {
    println(UserPrefs.username)   // Guest
    UserPrefs.username = "Alice"
    println(UserPrefs.username)   // Alice
}

Fonctions auxiliaires typées pour les préférences

Créez des fonctions auxiliaires typées pour chaque type de préférence primitif afin de simplifier les sites d’appel.

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
val store = mutableMapOf<String,Any?>()
fun stringPref(default: String) = object : ReadWriteProperty<Any?,String> {
    @Suppress("UNCHECKED_CAST")
    override fun getValue(t:Any?,p:KProperty<*>) = store.getOrDefault(p.name, default) as String
    override fun setValue(t:Any?,p:KProperty<*>,v:String) { store[p.name]=v }
}
fun intPref(default: Int) = object : ReadWriteProperty<Any?,Int> {
    @Suppress("UNCHECKED_CAST")
    override fun getValue(t:Any?,p:KProperty<*>) = store.getOrDefault(p.name, default) as Int
    override fun setValue(t:Any?,p:KProperty<*>,v:Int) { store[p.name]=v }
}
object Prefs {
    var name: String by stringPref("default")
    var count: Int by intPref(0)
}
fun main() { Prefs.name="Bob"; Prefs.count=5; println("${Prefs.name}: ${Prefs.count}") }

Délégué de journal d’audit

Enregistrez chaque modification de propriété avec son horodatage dans une liste d’audit — une solution idéale pour les scénarios de conformité ou de débogage.

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
val audit = mutableListOf<String>()
class AuditDelegate<T>(private var v: T) : ReadWriteProperty<Any?, T> {
    override fun getValue(t:Any?,p:KProperty<*>) = v
    override fun setValue(t:Any?,p:KProperty<*>,value:T) {
        audit += "[${System.currentTimeMillis()}] ${p.name}: $v -> $value"
        v = value
    }
}
var price: Double by AuditDelegate(9.99)
fun main() {
    price = 12.99
    price = 11.49
    audit.forEach(::println)
}

Validation et stockage dans une table associative

Combinez le stockage dans une table associative avec la validation : rejetez les valeurs non valides avant de les écrire dans la table.

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
val data = mutableMapOf<String, Any?>()
fun positiveInt(default: Int): ReadWriteProperty<Any?,Int> = object : ReadWriteProperty<Any?,Int> {
    @Suppress("UNCHECKED_CAST")
    override fun getValue(t:Any?,p:KProperty<*>)=data.getOrDefault(p.name,default) as Int
    override fun setValue(t:Any?,p:KProperty<*>,v:Int){
        require(v>=0){"${p.name} must be >= 0"}
        data[p.name]=v
    }
}
object Inventory { var stock: Int by positiveInt(100) }
fun main(){
    Inventory.stock=50; println(Inventory.stock)
    try { Inventory.stock=-1 } catch(e:Exception){ println(e.message) }
}

Schéma de composition de délégués

Composez plusieurs comportements de délégué à l’aide d’une API de type générateur : commencez avec un délégué de base, puis ajoutez la journalisation, la validation ou la mise en cache.

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
fun <T> ReadWriteProperty<Any?,T>.withLogging(): ReadWriteProperty<Any?,T> {
    val base = this
    return object : ReadWriteProperty<Any?,T> {
        override fun getValue(t:Any?,p:KProperty<*>): T {
            val v = base.getValue(t,p); println("get ${p.name}=$v"); return v
        }
        override fun setValue(t:Any?,p:KProperty<*>,v:T){
            println("set ${p.name}=$v"); base.setValue(t,p,v)
        }
    }
}

Cas pratique : schéma d’objet de configuration

Utilisez la délégation vers une table associative pour créer un objet de configuration à partir de sources externes telles que des variables d’environnement ou un fichier de configuration JSON.

class AppConfig(private val raw: Map<String, Any?>) {
    val host: String by raw
    val port: Int by raw
    val debug: Boolean by raw
}
fun main() {
    val env = mapOf("host" to "0.0.0.0", "port" to 8080, "debug" to true)
    val cfg = AppConfig(env)
    println("${cfg.host}:${cfg.port} debug=${cfg.debug}")
}

Vérification rapide

Que se passe-t-il lorsque vous déléguez une propriété à une Map ?

Récapitulatif

Les délégués permettent des schémas puissants : délégation vers une table associative pour les données dynamiques ou JSON, persistance de style SharedPreferences, journalisation d’audit à des fins de conformité et validation composable — le tout sans modifier les sites d’appel.

Gratuit pour commencer

Apprends Kotlin avec un tuteur IA — gratuit

Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.

Cours
51
Leçons
203

Questions Fréquemment Posées

La leçon « Délégués pour les préférences, les propriétés fondées sur une map et la journalisation » est-elle gratuite ?

Oui — le texte complet de « Délégués pour les préférences, les propriétés fondées sur une map et la journalisation » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Kotlin Academy, passe à CoddyKit PRO. Le cours Kotlin Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Délégués pour les préférences, les propriétés fondées sur une map et la journalisation » ?

Appliquez des délégués à SharedPreferences, au stockage par map et à la journalisation d’audit. Tu pratiques Kotlin Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Kotlin Academy ?

Aucune expérience préalable n'est requise. Kotlin Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.

Combien de temps prend la leçon « Délégués pour les préférences, les propriétés fondées sur une map et la journalisation » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Kotlin Academy ?

Oui. Chaque leçon Kotlin Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. by lazy : approfondissement de l’initialisation différée
  2. Délégués observable et vetoable
  3. Écrire un délégué ReadWriteProperty personnalisé
  4. Délégués pour les préférences, les propriétés fondées sur une map et la journalisation
← Retour à Kotlin Academy