HoRain 云小助手个人主页⛺️生活的理想就是为了理想的生活!⛳️ 推荐前些天发现了一个超棒的服务器购买网站性价比超高大内存超划算忍不住分享一下给大家。点击跳转到网站。目录⛳️ 推荐Kotlin 委托Delegation详解 核心概念委托的本质 两种委托类型1️⃣ 类委托Class Delegation概念基本语法对比普通实现 vs 委托实现实际应用场景2️⃣ 属性委托Property Delegation概念核心原理 内置委托实现1. lazy - 延迟初始化使用场景2. observable - 可观察属性3. vetoable - 可否决的属性4. map - 映射属性5. notNull - 非空属性 自定义委托只读属性委托ReadOnlyProperty可变属性委托ReadWriteProperty 实际应用场景1. ViewModel委托Android2. 配置管理3. 缓存委托⚠️ 注意事项1. 多属性共享委托实例2. Kotlin/JS兼容性3. 性能考虑 委托类型对比 最佳实践✅ 推荐使用场景❌ 避免使用场景 总结Kotlin 委托Delegation详解 核心概念委托是Kotlin中的一种语言特性允许对象将部分职责属性或方法委托给另一个辅助对象从而减少继承、实现代码复用。委托的本质类委托将接口的实现委托给另一个对象属性委托将属性的getter/setter逻辑委托给另一个对象核心关键字by 两种委托类型1️⃣ 类委托Class Delegation概念让一个类代理另一个类的功能自动转发接口方法。基本语法interface Printer { fun print(message: String) } class ConsolePrinter : Printer { override fun print(message: String) { println(Console: $message) } } // 委托实现 class DelegatingPrinter(printer: Printer) : Printer by printer fun main() { val console ConsolePrinter() val delegating DelegatingPrinter(console) delegating.print(Hello) // 输出: Console: Hello }对比普通实现 vs 委托实现// ❌ 普通实现 - 需要手动转发 class NormalPrinter(private val printer: Printer) : Printer { override fun print(message: String) { printer.print(message) // 手动转发 } } // ✅ 委托实现 - 自动转发 class DelegatedPrinter(printer: Printer) : Printer by printer实际应用场景// 装饰器模式实现 interface DataSource { fun read(): String fun write(data: String) } class FileDataSource(val filename: String) : DataSource { override fun read() File content override fun write(data: String) println(Write to file: $data) } // 添加缓存功能 class CachedDataSource(private val delegate: DataSource) : DataSource by delegate { private val cache mutableMapOfString, String() override fun read(): String { return cache.getOrPut(data) { delegate.read() } } }2️⃣ 属性委托Property Delegation概念将属性的访问逻辑getter/setter委托给专门的对象处理。核心原理// 编译器会将以下代码 val property: Type by Delegate() // 转换为 private val delegate Delegate() val property: Type get() delegate.getValue(this, thisRef::property) var property: Type by Delegate() // 转换为 var property: Type get() delegate.getValue(this, thisRef::property) set(value) delegate.setValue(this, thisRef::property, value) 内置委托实现1.lazy- 延迟初始化// 基础用法 val database: Database by lazy { Database.getInstance() // 只在首次访问时执行 } // 线程安全模式 val lazyValue1: String by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { 线程安全默认 } val lazyValue2: String by lazy(LazyThreadSafetyMode.PUBLICATION) { Publication模式 } val lazyValue3: String by lazy(LazyThreadSafetyMode.NONE) { 非线程安全性能更高 }使用场景class UserRepository { // 只在真正需要时才初始化 private val database by lazy { DatabaseHelper.getInstance() } fun getUser(id: Int): User? { return database.queryUser(id) // 此时才初始化database } }2.observable- 可观察属性import kotlin.properties.Delegates class User { var name: String by Delegates.observable(default) { property, oldValue, newValue - println(${property.name}: $oldValue - $newValue) } var age: Int by Delegates.observable(0) { _, old, new - println(Age changed: $old - $new) } } fun main() { val user User() user.name 张三 // 输出: name: default - 张三 user.age 25 // 输出: Age changed: 0 - 25 }3.vetoable- 可否决的属性class ValidatedUser { var age: Int by Delegates.vetoable(0) { _, old, new - println(尝试设置年龄: $old - $new) new in 0..150 // 返回true表示接受false表示拒绝 } } fun main() { val user ValidatedUser() user.age 25 // 成功输出: 尝试设置年龄: 0 - 25 user.age 200 // 失败值仍为25 println(user.age) // 输出: 25 }4.map- 映射属性class Person(map: MapString, Any?) { val name: String by map val age: Int by map val email: String? by map } fun main() { val data mapOf( name to 李四, age to 30, email to liexample.com ) val person Person(data) println(person.name) // 输出: 李四 println(person.age) // 输出: 30 println(person.email) // 输出: liexample.com }5.notNull- 非空属性import kotlin.properties.Delegates class LateInitExample { var name: String by Delegates.notNull() var age: Int by Delegates.notNull() } fun main() { val example LateInitExample() // example.name // 会抛出IllegalStateException example.name 王五 println(example.name) // 输出: 王五 } 自定义委托只读属性委托ReadOnlyPropertyimport kotlin.reflect.KProperty class LoggingDelegateT(private var value: T) { operator fun getValue(thisRef: Any?, property: KProperty*): T { println(${property.name} 被访问值为: $value) return value } } class User { var name: String by LoggingDelegate(default) } fun main() { val user User() println(user.name) // 输出: name 被访问值为: default // default }可变属性委托ReadWritePropertyclass ValidatedDelegateT( private var value: T, private val validator: (T) - Boolean ) { operator fun getValue(thisRef: Any?, property: KProperty*): T { return value } operator fun setValue(thisRef: Any?, property: KProperty*, newValue: T) { require(validator(newValue)) { Invalid value for ${property.name}: $newValue } println(${property.name} 从 $value 变为 $newValue) value newValue } } class Product { var price: Double by ValidatedDelegate(0.0) { it 0 } var stock: Int by ValidatedDelegate(0) { it 0 } } fun main() { val product Product() product.price 99.9 // ✅ product.stock 100 // ✅ // product.price -10 // ❌ 抛出异常 } 实际应用场景1. ViewModel委托Androidclass UserViewModel : ViewModel() { private val _users MutableLiveDataListUser() val users: LiveDataListUser _users // 使用委托简化访问 private var userData: User? by Delegates.observable(null) { _, _, _ - loadUserData() } private fun loadUserData() { // 加载用户数据 } }2. 配置管理class AppConfig { var apiUrl: String by Delegates.observable(https://api.example.com) { _, _, newValue - println(API URL changed to: $newValue) } var timeout: Int by Delegates.vetoable(30) { _, _, new - new in 10..60 } val databaseUrl: String by lazy { System.getenv(DATABASE_URL) ?: localhost:5432 } }3. 缓存委托class CacheDelegateK, V(private val loader: (K) - V) { private val cache mutableMapOfK, V() operator fun getValue(thisRef: Any?, property: KProperty*): (K) - V { return { key: K - cache.getOrPut(key) { loader(key) } } } } class DataRepository { private val dataLoader: (String) - String { key - println(Loading $key from database...) Data for $key } private val cachedData: (String) - String by CacheDelegate(dataLoader) fun getData(key: String): String { return cachedData(key) } } fun main() { val repo DataRepository() println(repo.getData(user1)) // Loading user1 from database... Data for user1 println(repo.getData(user1)) // Data for user1 (从缓存获取) }⚠️ 注意事项1. 多属性共享委托实例// ❌ 错误示例多个属性共享同一委托实例会导致冲突 val delegate Delegates.observable(0) { _, _, _ - } class BadExample { var a by delegate // 共享状态 var b by delegate // 共享状态会相互影响 } // ✅ 正确示例每个属性独立的委托实例 class GoodExample { var a by Delegates.observable(0) { _, _, _ - } var b by Delegates.observable(0) { _, _, _ - } }2. Kotlin/JS兼容性// 在Kotlin/JS中lazy委托的实现与JVM不同 // 特别是在多线程场景下JS是单线程的 val lazyValue by lazy { // 初始化逻辑 }3. 性能考虑// lazy委托有轻微的性能开销线程安全检查 // 对于简单且快速初始化的属性直接初始化可能更好 // ❌ 过度使用 val simpleValue by lazy { constant } // ✅ 直接初始化 val simpleValue constant 委托类型对比委托类型适用场景线程安全性能开销lazy延迟初始化✅可配置低observable属性监听❌低vetoable属性验证❌低map数据映射❌极低notNull延迟赋值❌极低 最佳实践✅ 推荐使用场景延迟初始化资源密集型对象属性监听UI绑定、日志记录数据验证输入验证、范围检查配置管理动态配置、环境变量缓存策略结果缓存、懒加载❌ 避免使用场景简单的常量属性需要频繁访问且初始化成本低的属性多个属性共享同一委托实例除非有意设计 总结Kotlin委托是一种强大的语言特性通过by关键字实现了类委托减少继承实现接口的自动转发属性委托封装属性访问逻辑实现延迟初始化、观察者模式等功能核心优势✅ 减少样板代码✅ 提高代码复用性✅ 增强代码灵活性✅ 支持多种设计模式掌握委托特性能让你写出更简洁、更优雅的Kotlin代码❤️❤️❤️本人水平有限如有纰漏欢迎各位大佬评论批评指正如果觉得这篇文对你有帮助的话也请给个点赞、收藏下吧非常感谢! Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧