Kotlin Academy · Aula

Delegados para preferências, propriedades baseadas em mapas e registro

Aplique delegados a SharedPreferences, ao armazenamento em mapas e ao registro de auditoria.

Aula 4 de 413 etapas

Delegados para preferências, propriedades baseadas em mapas e registro é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Kotlin Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Kotlin Academy inclui 4 aulas no total.

Propriedades baseadas em mapas

O Kotlin permite delegar propriedades diretamente a um Map. A leitura da propriedade procura o nome dela no mapa.

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
}

Delegado de MutableMap

Para propriedades mutáveis, delegue a um MutableMap; as alterações atualizarão o mapa subjacente.

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
}

Desserialização de JSON com delegado de mapa

Analise um mapa semelhante ao JSON e exponha seus campos como propriedades tipadas usando delegação de mapa — uma ótima opção para dados dinâmicos.

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
}

Padrão de delegado com registro

Envolva qualquer delegado com registro para rastrear de forma transparente cada leitura e gravação em todas as propriedades delegadas.

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" }

Combinando mapa e registro

Adicione uma camada de registro ao redor da delegação de mapa para obter rastreabilidade completa do acesso a propriedades dinâmicas.

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) }

Delegado no estilo SharedPreferences

Um delegado que armazena valores em um mapa subjacente que simula SharedPreferences — adapte-o às preferências reais do Android substituindo o mapa por chamadas às preferências reais.

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
}

Auxiliares tipados de preferências

Crie funções auxiliares tipadas para cada tipo primitivo de preferência, deixando os pontos de chamada mais simples.

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}") }

Delegado de registro de auditoria

Registre cada alteração de propriedade com o respectivo carimbo de data e hora em uma lista de auditoria — ideal para cenários de conformidade ou depuração.

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)
}

Validação e armazenamento em mapa

Combine o armazenamento em mapa com a validação: rejeite valores inválidos antes de gravá-los no mapa.

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) }
}

Padrão de composição de delegados

Componha vários comportamentos de delegados usando uma API no estilo de construtor: comece com um delegado básico e adicione registro, validação ou armazenamento em 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)
        }
    }
}

Prática: padrão de objeto de configuração do mundo real

Use a delegação de mapa para criar um objeto de configuração a partir de fontes externas, como variáveis de ambiente ou um arquivo de configuração 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}")
}

Verificação rápida

O que acontece quando você delega uma propriedade a um Map?

Revisão

Os delegados viabilizam padrões poderosos: delegação a mapas para dados dinâmicos ou JSON, persistência no estilo SharedPreferences, registro de auditoria para conformidade e validação combinável — tudo sem alterar os pontos de chamada.

Grátis para começar

Aprenda Kotlin com um tutor de IA — grátis

Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.

Cursos
51
Aulas
203

Perguntas Frequentes

A aula “Delegados para preferências, propriedades baseadas em mapas e registro” é grátis?

Sim — o texto completo de “Delegados para preferências, propriedades baseadas em mapas e registro” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Kotlin Academy, atualize para CoddyKit PRO. O curso de Kotlin Academy inclui 4 aulas no total.

O que vou aprender em “Delegados para preferências, propriedades baseadas em mapas e registro”?

Aplique delegados a SharedPreferences, ao armazenamento em mapas e ao registro de auditoria. Você pratica Kotlin Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Kotlin Academy?

Nenhuma experiência prévia é necessária. Kotlin Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.

Quanto tempo leva a aula “Delegados para preferências, propriedades baseadas em mapas e registro”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Kotlin Academy?

Sim. Cada aula de Kotlin Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. by lazy: análise detalhada da inicialização adiada
  2. Delegados observable e vetoable
  3. Escrevendo um delegado ReadWriteProperty personalizado
  4. Delegados para preferências, propriedades baseadas em mapas e registro
← Voltar para Kotlin Academy