kotlin 委托笔记

34 阅读8分钟

Kotlin 委托(Delegation)详解

委托是 Kotlin 中一种强大的设计模式,它允许对象将部分职责委托给另一个对象来完成。Kotlin 通过 by 关键字原生支持委托模式。

一、委托的基本概念

1. 委托模式 vs 继承

// 继承:is-a 关系
open class Animal {
    open fun makeSound() = "Some sound"
}

class Dog : Animal() {
    override fun makeSound() = "Bark"
}

// 委托:has-a 关系
interface SoundMaker {
    fun makeSound(): String
}

class DogSoundMaker : SoundMaker {
    override fun makeSound() = "Bark"
}

class Dog(private val soundMaker: SoundMaker) : SoundMaker by soundMaker {
    // Dog 委托给 soundMaker 来实现 makeSound()
}

fun main() {
    val dog1 = Dog()  // 继承
    println(dog1.makeSound())  // Bark
    
    val dog2 = Dog(DogSoundMaker())  // 委托
    println(dog2.makeSound())  // Bark
}

二、类委托(Class Delegation)

1. 基本语法

interface Printer {
    fun printMessage(message: String)
    fun printError(error: String)
}

class ConsolePrinter : Printer {
    override fun printMessage(message: String) {
        println("INFO: $message")
    }
    
    override fun printError(error: String) {
        println("ERROR: $error")
    }
}

// 委托给 consolePrinter
class Logger(private val consolePrinter: Printer) : Printer by consolePrinter {
    // 可以添加额外的方法
    fun logWithTimestamp(message: String) {
        val timestamp = System.currentTimeMillis()
        printMessage("[$timestamp] $message")
    }
    
    // 也可以重写委托的方法
    override fun printError(error: String) {
        consolePrinter.printError("!!! $error !!!")
    }
}

fun main() {
    val consolePrinter = ConsolePrinter()
    val logger = Logger(consolePrinter)
    
    logger.printMessage("Hello")  // 委托给 ConsolePrinter
    // 输出: INFO: Hello
    
    logger.logWithTimestamp("World")
    // 输出: INFO: [1645678901234] World
    
    logger.printError("Something went wrong")
    // 输出: ERROR: !!! Something went wrong !!!
}

2. 多接口委托

interface Reader {
    fun read(): String
}

interface Writer {
    fun write(content: String)
}

class FileHandler : Reader, Writer {
    override fun read(): String {
        return "File content"
    }
    
    override fun write(content: String) {
        println("Writing: $content")
    }
}

// 委托给多个接口
class DocumentProcessor(
    private val reader: Reader,
    private val writer: Writer
) : Reader by reader, Writer by writer {
    
    fun process() {
        val content = read()  // 委托给 reader
        val processed = content.uppercase()
        write(processed)      // 委托给 writer
    }
}

fun main() {
    val handler = FileHandler()
    val processor = DocumentProcessor(handler, handler)
    processor.process()
    // 输出: Writing: FILE CONTENT
}

3. 动态代理模式

import java.lang.reflect.Proxy

interface Service {
    fun serve()
}

class RealService : Service {
    override fun serve() {
        println("Real service serving...")
    }
}

// 动态代理
class ServiceProxy(private val realService: Service) : Service by realService {
    override fun serve() {
        println("Before serving...")
        realService.serve()
        println("After serving...")
    }
}

// Kotlin 风格代理
class LoggingServiceProxy(private val target: Service) : Service by target {
    override fun serve() {
        println("[LOG] Service.serve() called at ${System.currentTimeMillis()}")
        target.serve()
        println("[LOG] Service.serve() completed")
    }
}

fun main() {
    val realService = RealService()
    val proxy = ServiceProxy(realService)
    proxy.serve()
    // 输出:
    // Before serving...
    // Real service serving...
    // After serving...
    
    val loggingProxy = LoggingServiceProxy(realService)
    loggingProxy.serve()
}

三、属性委托(Property Delegation)

1. 基本语法

import kotlin.reflect.KProperty

class Delegate {
    private var storedValue: String = ""
    
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        println("Getting value of '${property.name}' = $storedValue")
        return storedValue
    }
    
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("Setting value of '${property.name}' from $storedValue to $value")
        storedValue = value
    }
}

class Example {
    var p: String by Delegate()  // 属性委托
}

fun main() {
    val example = Example()
    
    example.p = "Hello"  // 调用 Delegate.setValue()
    // 输出: Setting value of 'p' from  to Hello
    
    println(example.p)   // 调用 Delegate.getValue()
    // 输出: Getting value of 'p' = Hello
    //       Hello
}

2. 延迟属性(Lazy Properties)

class HeavyResource {
    init {
        println("HeavyResource initialized - expensive operation!")
        Thread.sleep(1000)  // 模拟耗时初始化
    }
    
    fun doWork() {
        println("HeavyResource working...")
    }
}

class ResourceManager {
    // 延迟初始化:第一次访问时才创建
    val heavyResource: HeavyResource by lazy {
        println("Creating HeavyResource...")
        HeavyResource()
    }
    
    // 线程安全的延迟初始化
    val threadSafeResource: HeavyResource by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
        HeavyResource()
    }
    
    // 可空延迟属性
    val nullableResource: HeavyResource? by lazy {
        if (System.currentTimeMillis() % 2 == 0L) {
            HeavyResource()
        } else {
            null
        }
    }
    
    // 带参数的延迟初始化
    val configuredResource by lazy {
        val config = loadConfig()
        HeavyResource().apply {
            // 基于配置初始化
        }
    }
    
    private fun loadConfig() = "config"
}

fun main() {
    val manager = ResourceManager()
    
    println("ResourceManager created")
    // 此时 HeavyResource 还没有被创建
    
    println("\nFirst access:")
    manager.heavyResource.doWork()
    // 输出: Creating HeavyResource...
    //       HeavyResource initialized - expensive operation!
    //       HeavyResource working...
    
    println("\nSecond access:")
    manager.heavyResource.doWork()
    // 输出: HeavyResource working...
    // 注意:不会再次初始化!
}

3. 可观察属性(Observable Properties)

import kotlin.properties.Delegates

class User {
    var name: String by Delegates.observable("<no name>") { 
        property, oldValue, newValue ->
        println("$oldValue -> $newValue")
    }
    
    var age: Int by Delegates.observable(0) { _, old, new ->
        when {
            new > old -> println("年龄增长: $old -> $new")
            new < old -> println("年龄减小: $old -> $new")
            else -> println("年龄未变: $old")
        }
    }
    
    var email: String by Delegates.vetoable("") { _, old, new ->
        // 否决:如果新邮箱不包含@,则拒绝修改
        if (new.contains("@")) {
            println("邮箱从 $old 更新为 $new")
            true  // 接受修改
        } else {
            println("拒绝无效邮箱: $new")
            false  // 拒绝修改
        }
    }
    
    // 带自定义逻辑的可观察属性
    var score: Int by Delegates.observable(0) { prop, old, new ->
        println("分数变化: $old -> $new")
        
        when {
            new >= 90 -> println("优秀!")
            new >= 60 -> println("及格")
            else -> println("不及格")
        }
    }
}

fun main() {
    val user = User()
    
    user.name = "Alice"
    // 输出: <no name> -> Alice
    
    user.name = "Bob"
    // 输出: Alice -> Bob
    
    user.age = 25
    // 输出: 年龄增长: 0 -> 25
    
    user.age = 25
    // 输出: 年龄未变: 25
    
    user.email = "alice@example.com"
    // 输出: 邮箱从  更新为 alice@example.com
    
    user.email = "invalid-email"
    // 输出: 拒绝无效邮箱: invalid-email
    println("邮箱仍然是: ${user.email}")
    // 输出: 邮箱仍然是: alice@example.com
    
    user.score = 85
    // 输出: 分数变化: 0 -> 85
    //       及格
}

4. Map 属性委托

class Configuration(map: Map<String, Any?>) {
    // 从 Map 中读取属性
    val host: String by map
    val port: Int by map
    val timeout: Long by map
    val sslEnabled: Boolean by map
    val maxConnections: Int? by map  // 可空属性
    
    // MutableMap 用于可变属性
    class MutableConfig(map: MutableMap<String, Any?>) {
        var debugMode: Boolean by map
        var logLevel: String by map
        var cacheSize: Int by map
    }
}

// JSON/YAML 配置示例
data class AppConfig(
    val configMap: Map<String, Any?>
) {
    val database: DatabaseConfig by configMap
    val server: ServerConfig by configMap
    val features: FeaturesConfig by configMap
}

// 嵌套配置
data class DatabaseConfig(val url: String, val user: String, val password: String)
data class ServerConfig(val port: Int, val host: String)
data class FeaturesConfig(val analytics: Boolean, val notifications: Boolean)

fun main() {
    // 从 Map 创建配置
    val configMap = mapOf(
        "host" to "localhost",
        "port" to 8080,
        "timeout" to 30000L,
        "sslEnabled" to true,
        "maxConnections" to 100
    )
    
    val config = Configuration(configMap)
    println("Host: ${config.host}")        // localhost
    println("Port: ${config.port}")        // 8080
    println("SSL: ${config.sslEnabled}")   // true
    
    // 可变配置
    val mutableMap = mutableMapOf(
        "debugMode" to false,
        "logLevel" to "INFO",
        "cacheSize" to 1024
    )
    
    val mutableConfig = Configuration.MutableConfig(mutableMap)
    println("初始日志级别: ${mutableConfig.logLevel}")  // INFO
    
    mutableConfig.logLevel = "DEBUG"
    println("修改后Map: $mutableMap")  
    // 输出: {debugMode=false, logLevel=DEBUG, cacheSize=1024}
}

5. 自定义属性委托

import kotlin.reflect.KProperty
import java.text.SimpleDateFormat
import java.util.*

// 1. 日期格式化委托
class DateDelegate(private val pattern: String = "yyyy-MM-dd") {
    private val formatter = SimpleDateFormat(pattern)
    
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return formatter.format(Date())
    }
    
    // 只读属性不需要 setValue
}

// 2. 缓存委托
class CacheDelegate<T : Any>(
    private val initializer: () -> T
) {
    private var cachedValue: T? = null
    
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return cachedValue ?: initializer().also { cachedValue = it }
    }
    
    fun clearCache() {
        cachedValue = null
    }
}

// 3. 验证委托
class ValidatedDelegate<T>(
    private val initialValue: T,
    private val validator: (T) -> Boolean
) {
    private var value: T = initialValue
    
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value
    
    operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: T) {
        if (validator(newValue)) {
            value = newValue
        } else {
            throw IllegalArgumentException("Invalid value for ${property.name}: $newValue")
        }
    }
}

// 4. 线程安全委托
class SynchronizedDelegate<T>(private var value: T) {
    private val lock = Any()
    
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        synchronized(lock) {
            return value
        }
    }
    
    operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: T) {
        synchronized(lock) {
            value = newValue
        }
    }
}

// 使用示例
class UserProfile {
    // 日期格式化
    val currentDate: String by DateDelegate()
    val timestamp: String by DateDelegate("yyyy-MM-dd HH:mm:ss")
    
    // 缓存
    val expensiveCalculation: String by CacheDelegate {
        println("计算中...")
        Thread.sleep(1000)
        "计算结果: ${System.currentTimeMillis()}"
    }
    
    // 验证
    var age: Int by ValidatedDelegate(0) { it in 0..150 }
    var email: String by ValidatedDelegate("") { it.contains("@") }
    
    // 线程安全
    var balance: Double by SynchronizedDelegate(0.0)
}

fun main() {
    val profile = UserProfile()
    
    println("当前日期: ${profile.currentDate}")
    println("时间戳: ${profile.timestamp}")
    
    println("\n第一次访问缓存:")
    println(profile.expensiveCalculation)
    println("\n第二次访问缓存(使用缓存):")
    println(profile.expensiveCalculation)
    
    println("\n验证属性:")
    profile.age = 25  // 正常
    println("年龄: ${profile.age}")
    
    try {
        profile.age = 200  // 抛出异常
    } catch (e: IllegalArgumentException) {
        println(e.message)  // Invalid value for age: 200
    }
    
    profile.email = "test@example.com"  // 正常
    println("邮箱: ${profile.email}")
}

四、标准库中的委托

1. Delegates 工具类

import kotlin.properties.Delegates

class Settings {
    // 1. notNull: 非空但延迟初始化
    var notNullValue: String by Delegates.notNull<String>()
    
    // 2. observable: 可观察属性
    var observableValue: Int by Delegates.observable(0) { _, old, new ->
        println("值从 $old 变为 $new")
    }
    
    // 3. vetoable: 可否决属性
    var vetoableValue: String by Delegates.vetoable("default") { _, old, new ->
        new.length <= 10  // 只接受长度小于等于10的字符串
    }
}

fun main() {
    val settings = Settings()
    
    // notNull 必须在使用前初始化
    // println(settings.notNullValue)  // 抛出 IllegalStateException
    
    settings.notNullValue = "Hello"
    println(settings.notNullValue)  // Hello
    
    settings.observableValue = 10  // 输出: 值从 0 变为 10
    settings.observableValue = 20  // 输出: 值从 10 变为 20
    
    settings.vetoableValue = "short"
    println("vetoableValue: ${settings.vetoableValue}")  // short
    
    settings.vetoableValue = "this string is too long"
    println("vetoableValue: ${settings.vetoableValue}")  // 仍然是 short
}

2. 使用 provideDelegate 操作符

import kotlin.reflect.KProperty
import kotlin.properties.ReadOnlyProperty

class ResourceDelegate<T : Any>(
    private val provider: () -> T
) : ReadOnlyProperty<Any?, T> {
    private var value: T? = null
    
    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        if (value == null) {
            value = provider()
        }
        return value!!
    }
}

class ResourceLoader<T : Any>(private val provider: () -> T) {
    // provideDelegate 在属性委托创建时调用
    operator fun provideDelegate(
        thisRef: Any?,
        prop: KProperty<*>
    ): ReadOnlyProperty<Any?, T> {
        println("为属性 '${prop.name}' 创建委托")
        
        // 可以在这里进行验证或初始化
        if (prop.name.contains("secret")) {
            throw IllegalArgumentException("属性名不能包含 'secret'")
        }
        
        return ResourceDelegate(provider)
    }
}

class AppConfig {
    val databaseUrl: String by ResourceLoader { 
        "jdbc:mysql://localhost:3306/mydb" 
    }
    
    val apiKey: String by ResourceLoader {
        System.getenv("API_KEY") ?: "default-key"
    }
    
    // val secretInfo: String by ResourceLoader { "secret" }  // 抛出异常
}

fun main() {
    val config = AppConfig()
    println("数据库URL: ${config.databaseUrl}")
    println("API密钥: ${config.apiKey}")
}

五、实际应用场景

1. Android View 属性委托

// Kotlin Android 扩展的替代方案
class ActivityDelegate {
    // 视图绑定委托
    inline fun <reified T : View> bindView(id: Int): ReadOnlyProperty<Activity, T> {
        return object : ReadOnlyProperty<Activity, T> {
            private var value: T? = null
            
            override fun getValue(thisRef: Activity, property: KProperty<*>): T {
                if (value == null) {
                    value = thisRef.findViewById(id)
                }
                return value!!
            }
        }
    }
    
    // 参数委托
    inline fun <reified T> argument(key: String): ReadOnlyProperty<Fragment, T> {
        return object : ReadOnlyProperty<Fragment, T> {
            override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
                return thisRef.arguments?.get(key) as? T 
                    ?: throw IllegalArgumentException("参数 $key 不存在或类型不匹配")
            }
        }
    }
}

// 使用示例
class MainActivity : AppCompatActivity() {
    private val delegate = ActivityDelegate()
    
    // 视图绑定
    private val textView: TextView by delegate.bindView(R.id.text_view)
    private val button: Button by delegate.bindView(R.id.button)
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        textView.text = "Hello, Delegation!"
        button.setOnClickListener {
            // 处理点击
        }
    }
}

class UserFragment : Fragment() {
    private val delegate = ActivityDelegate()
    
    // 参数委托
    private val userId: String by delegate.argument("userId")
    private val userName: String by delegate.argument("userName")
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        println("用户ID: $userId")
        println("用户名: $userName")
    }
}

2. 数据库访问委托

// Room 或 SQLDelight 的委托扩展
class DatabaseDelegate {
    // 数据库查询委托
    fun <T> cachedQuery(
        query: () -> T
    ): ReadOnlyProperty<Any?, T> {
        return object : ReadOnlyProperty<Any?, T> {
            private var cachedValue: T? = null
            
            override fun getValue(thisRef: Any?, property: KProperty<*>): T {
                if (cachedValue == null) {
                    cachedValue = query()
                }
                return cachedValue!!
            }
            
            fun invalidate() {
                cachedValue = null
            }
        }
    }
    
    // 事务委托
    fun <T> transaction(
        database: Database,
        body: () -> T
    ): ReadOnlyProperty<Any?, T> {
        return object : ReadOnlyProperty<Any?, T> {
            override fun getValue(thisRef: Any?, property: KProperty<*>): T {
                return database.transaction {
                    body()
                }
            }
        }
    }
}

// 使用示例
class UserRepository(
    private val userDao: UserDao,
    private val database: Database
) {
    private val delegate = DatabaseDelegate()
    
    // 缓存用户查询
    val allUsers: List<User> by delegate.cachedQuery {
        userDao.getAll()
    }
    
    // 事务操作
    val userCount: Int by delegate.transaction(database) {
        userDao.getCount()
    }
    
    fun refreshUsers() {
        // 使缓存失效
        // 需要反射来访问委托的 invalidate 方法
        // 或者使用不同的设计模式
    }
}

3. 权限和安全性委托

import kotlin.reflect.KProperty

// 权限检查委托
class PermissionDelegate<T>(
    private val permission: String,
    private val defaultValue: T,
    private val authorizedValue: T
) {
    private val securityContext = SecurityContext()
    
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return if (securityContext.hasPermission(permission)) {
            authorizedValue
        } else {
            defaultValue
        }
    }
    
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        if (securityContext.hasPermission(permission)) {
            // 存储逻辑...
            println("设置 ${property.name} = $value")
        } else {
            throw SecurityException("缺少权限: $permission")
        }
    }
}

// 加密属性委托
class EncryptedDelegate<T>(
    private val encryptor: Encryptor,
    private val initialValue: T
) {
    private var encryptedValue: String = encryptor.encrypt(initialValue.toString())
    
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        val decrypted = encryptor.decrypt(encryptedValue)
        return convertFromString(decrypted)
    }
    
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        encryptedValue = encryptor.encrypt(value.toString())
    }
    
    @Suppress("UNCHECKED_CAST")
    private fun convertFromString(value: String): T {
        return when (initialValue) {
            is String -> value as T
            is Int -> value.toInt() as T
            is Boolean -> value.toBoolean() as T
            else -> throw IllegalArgumentException("不支持的类型")
        }
    }
}

// 使用示例
class SecureSettings {
    // 权限控制
    var adminSetting: String by PermissionDelegate(
        "admin.settings",
        defaultValue = "普通用户设置",
        authorizedValue = "管理员设置"
    )
    
    // 加密存储
    var apiKey: String by EncryptedDelegate(
        encryptor = AesEncryptor(),
        initialValue = ""
    )
    
    var secretNumber: Int by EncryptedDelegate(
        encryptor = AesEncryptor(),
        initialValue = 0
    )
}

// 模拟安全上下文
class SecurityContext {
    private val permissions = mutableSetOf("user.read", "user.write")
    
    fun hasPermission(permission: String): Boolean {
        return permission in permissions
    }
    
    fun grantPermission(permission: String) {
        permissions.add(permission)
    }
}

// 模拟加密器
interface Encryptor {
    fun encrypt(text: String): String
    fun decrypt(encrypted: String): String
}

class AesEncryptor : Encryptor {
    override fun encrypt(text: String): String {
        // 模拟加密
        return "encrypted_${text.reversed()}"
    }
    
    override fun decrypt(encrypted: String): String {
        // 模拟解密
        return encrypted.removePrefix("encrypted_").reversed()
    }
}

fun main() {
    val settings = SecureSettings()
    
    println("管理员设置: ${settings.adminSetting}")
    // 输出: 管理员设置: 普通用户设置
    
    // 授予权限
    val context = SecurityContext()
    context.grantPermission("admin.settings")
    
    println("管理员设置: ${settings.adminSetting}")
    // 输出: 管理员设置: 管理员设置
    
    // 加密属性
    settings.apiKey = "my-secret-api-key"
    println("加密的API密钥: ${settings.apiKey}")
    // 实际存储的是加密值
}

4. 缓存和性能优化

import kotlin.reflect.KProperty
import kotlin.system.measureTimeMillis

// 性能监控委托
class TimedDelegate<T>(private val delegate: () -> T) {
    private var cachedValue: T? = null
    
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        val time = measureTimeMillis {
            if (cachedValue == null) {
                cachedValue = delegate()
            }
        }
        println("${property.name} 获取耗时: ${time}ms")
        return cachedValue!!
    }
    
    fun clearCache() {
        cachedValue = null
    }
}

// 记忆化委托(Memoization)
class MemoizeDelegate<T, R>(private val function: (T) -> R) {
    private val cache = mutableMapOf<T, R>()
    
    operator fun getValue(thisRef: Any?, property: KProperty<*>): (T) -> R {
        return { param: T ->
            cache.getOrPut(param) {
                function(param)
            }
        }
    }
    
    fun clearCache() {
        cache.clear()
    }
}

// 使用示例
class MathOperations {
    // 带计时的延迟计算
    val heavyCalculation: String by TimedDelegate {
        Thread.sleep(1000)  // 模拟耗时计算
        "计算结果"
    }
    
    // 记忆化函数
    val factorial: (Int) -> Long by MemoizeDelegate { n ->
        if (n <= 1) 1L else n * factorial(n - 1)
    }
    
    val fibonacci: (Int) -> Long by MemoizeDelegate { n ->
        when (n) {
            0 -> 0L
            1 -> 1L
            else -> fibonacci(n - 1) + fibonacci(n - 2)
        }
    }
}

fun main() {
    val math = MathOperations()
    
    println("第一次获取:")
    println(math.heavyCalculation)  // 输出耗时信息
    
    println("\n第二次获取(使用缓存):")
    println(math.heavyCalculation)  // 几乎没有耗时
    
    println("\n计算阶乘:")
    println("5! = ${math.factorial(5)}")
    println("10! = ${math.factorial(10)}")
    
    println("\n计算斐波那契数列:")
    println("fib(10) = ${math.fibonacci(10)}")
    println("fib(20) = ${math.fibonacci(20)}")
    println("fib(30) = ${math.fibonacci(30)}")  // 因为有记忆化,很快
}

六、委托的高级特性

1. 委托属性转换

import kotlin.reflect.KProperty

// 属性转换委托
class TransformDelegate<T, R>(
    private val getter: (T) -> R,
    private val setter: (R) -> T?
) {
    private var rawValue: T? = null
    
    operator fun getValue(thisRef: Any?, property: KProperty<*>): R {
        return rawValue?.let { getter(it) } 
            ?: throw IllegalStateException("属性未初始化")
    }
    
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: R) {
        rawValue = setter(value)
    }
}

// 使用示例
class UserPreferences {
    // 存储为毫秒,提供为日期字符串
    var lastLogin: String by TransformDelegate(
        getter = { millis ->
            java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                .format(Date(millis))
        },
        setter = { dateString ->
            java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                .parse(dateString)?.time
        }
    )
    
    // 存储为字符串,提供为枚举
    var theme: Theme by TransformDelegate(
        getter = { string -> Theme.valueOf(string) },
        setter = { enum -> enum.name }
    )
}

enum class Theme { LIGHT, DARK, SYSTEM }

fun main() {
    val prefs = UserPreferences()
    
    prefs.lastLogin = "2024-01-15 14:30:00"
    println("最后登录: ${prefs.lastLogin}")
    
    prefs.theme = Theme.DARK
    println("主题: ${prefs.theme}")
}

2. 委托属性组合

import kotlin.reflect.KProperty
import kotlin.properties.ReadOnlyProperty
import kotlin.properties.Delegates

// 组合多个委托
class CombinedDelegate<T>(
    private vararg val delegates: ReadOnlyProperty<Any?, T>
) : ReadOnlyProperty<Any?, T> {
    
    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        // 返回第一个非空委托的值
        for (delegate in delegates) {
            try {
                return delegate.getValue(thisRef, property)
            } catch (e: Exception) {
                // 继续尝试下一个委托
            }
        }
        throw IllegalStateException("所有委托都失败了")
    }
}

// 使用示例
class FallbackConfiguration {
    private val primaryConfig = mapOf("timeout" to 5000)
    private val secondaryConfig = mapOf("timeout" to 3000)
    private val defaultConfig = mapOf("timeout" to 1000)
    
    val timeout: Int by CombinedDelegate(
        // 尝试从主配置读取
        object : ReadOnlyProperty<Any?, Int> {
            override fun getValue(thisRef: Any?, property: KProperty<*>): Int {
                return primaryConfig[property.name] as? Int
                    ?: throw NoSuchElementException()
            }
        },
        // 尝试从备选配置读取
        object : ReadOnlyProperty<Any?, Int> {
            override fun getValue(thisRef: Any?, property: KProperty<*>): Int {
                return secondaryConfig[property.name] as? Int
                    ?: throw NoSuchElementException()
            }
        },
        // 使用默认值
        object : ReadOnlyProperty<Any?, Int> {
            override fun getValue(thisRef: Any?, property: KProperty<*>): Int {
                return defaultConfig[property.name] as Int
            }
        }
    )
}

fun main() {
    val config = FallbackConfiguration()
    println("超时设置: ${config.timeout}ms")  // 5000
    
    // 即使 primaryConfig 缺少某个属性,也能正常工作
}

3. 委托属性的反射

import kotlin.reflect.KProperty
import kotlin.reflect.full.declaredMemberProperties

// 反射访问委托属性
class ReflectiveUser {
    var name: String by Delegates.observable("") { _, old, new ->
        println("名字从 '$old' 改为 '$new'")
    }
    
    var age: Int by Delegates.vetoable(0) { _, _, new ->
        new >= 0
    }
    
    val metadata: Map<String, Any> by lazy {
        mapOf("created" to System.currentTimeMillis())
    }
}

// 委托属性分析器
class DelegateAnalyzer {
    fun analyze(obj: Any) {
        val kClass = obj::class
        
        kClass.declaredMemberProperties.forEach { property ->
            println("\n分析属性: ${property.name}")
            println("类型: ${property.returnType}")
            
            try {
                val value = property.getter.call(obj)
                println("值: $value")
                
                // 检查是否是委托属性
                if (property.name.startsWith("delegate")) {
                    println("这是一个委托属性")
                }
            } catch (e: Exception) {
                println("获取值失败: ${e.message}")
            }
        }
    }
}

fun main() {
    val user = ReflectiveUser()
    user.name = "Alice"
    user.age = 25
    
    val analyzer = DelegateAnalyzer()
    analyzer.analyze(user)
}

七、最佳实践和注意事项

1. 性能考虑

class PerformanceConsiderations {
    // ✅ 好的做法:对于计算成本高的属性使用 lazy
    val expensiveResource by lazy { 
        HeavyResource() 
    }
    
    // ❌ 不好的做法:对于简单属性过度使用委托
    // val simpleValue by Delegates.notNull<String>()  // 不必要的开销
    
    // ✅ 好的做法:直接属性访问
    val simpleValue: String = "直接值"
    
    // ✅ 对于需要监听变化的属性使用 observable
    var importantValue: String by Delegates.observable("") { _, old, new ->
        onImportantValueChanged(old, new)
    }
    
    private fun onImportantValueChanged(old: String, new: String) {
        // 处理变化
    }
}

2. 线程安全

import java.util.concurrent.atomic.AtomicReference
import kotlin.properties.Delegates

class ThreadSafeDelegation {
    // 使用同步委托
    var sharedCounter: Int by Delegates.observable(0) { _, old, new ->
        // observable 本身不是线程安全的
        println("计数器: $old -> $new")
    }
    
    // 更好的线程安全方案
    private val atomicCounter = AtomicReference(0)
    
    val threadSafeCounter: Int
        get() = atomicCounter.get()
    
    fun incrementCounter() {
        atomicCounter.updateAndGet { it + 1 }
    }
    
    // 自定义线程安全委托
    class SynchronizedDelegate<T>(initialValue: T) {
        @Volatile
        private var value: T = initialValue
        private val lock = Any()
        
        operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
            return synchronized(lock) { value }
        }
        
        operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: T) {
            synchronized(lock) {
                value = newValue
            }
        }
    }
    
    var safeValue: String by SynchronizedDelegate("初始值")
}

3. 测试委托属性

import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith

class DelegatePropertyTest {
    @Test
    fun testLazyDelegate() {
        var initializationCount = 0
        
        val lazyValue by lazy {
            initializationCount++
            "初始化值"
        }
        
        assertEquals(0, initializationCount, "延迟属性不应立即初始化")
        
        val value1 = lazyValue
        assertEquals(1, initializationCount, "第一次访问应初始化")
        assertEquals("初始化值", value1)
        
        val value2 = lazyValue
        assertEquals(1, initializationCount, "第二次访问不应重新初始化")
        assertEquals("初始化值", value2)
    }
    
    @Test
    fun testObservableDelegate() {
        var lastChange: Pair<String, String>? = null
        
        val observableValue by Delegates.observable("初始") { _, old, new ->
            lastChange = old to new
        }
        
        // 触发变化
        observableValue = "新值"
        
        assertEquals("初始" to "新值", lastChange)
    }
    
    @Test
    fun testVetoableDelegate() {
        var changes = mutableListOf<String>()
        
        val vetoableValue by Delegates.vetoable("初始") { _, old, new ->
            val allowed = new.length <= 10
            if (allowed) {
                changes.add("$old -> $new")
            }
            allowed
        }
        
        vetoableValue = "短"  // 允许
        assertEquals("短", vetoableValue)
        
        vetoableValue = "这个字符串太长了应该被拒绝"  // 拒绝
        assertEquals("短", vetoableValue, "过长的值应被拒绝")
        
        assertEquals(listOf("初始 -> 短"), changes)
    }
}

总结

Kotlin 委托是一种强大的语言特性,主要分为:

  1. 类委托

    • 使用 by 关键字将接口实现委托给另一个对象
    • 减少样板代码,实现更好的组合而非继承
    • 支持多个接口委托
  2. 属性委托

    • Lazy:延迟初始化,首次访问时计算
    • Observable:监听属性变化
    • Vetoable:验证并可能否决属性修改
    • Map 委托:从 Map 中读写属性
    • 自定义委托:实现 getValue/setValue 方法
  3. 实际应用

    • Android 视图绑定
    • 配置管理
    • 权限控制
    • 缓存和性能优化
    • 数据库访问
  4. 最佳实践

    • 合理使用委托,避免不必要的性能开销
    • 考虑线程安全性
    • 编写可测试的委托
    • 使用标准委托优先于自定义委托

委托模式使 Kotlin 代码更加简洁、可维护和表达性强,是现代 Kotlin 开发中不可或缺的特性。