在 Kotlin 中,屬性委托和類委托是兩種通過 by
關鍵字實現的強大特性,它們通過“委托”機制將行為或實現邏輯委托給其他對象,從而實現代碼的復用和解耦。
1 屬性委托
定義: 允許把屬性的 get
和 set
方法的具體實現委托給另一個對象。
語法:
var/val 屬性名: 類型 by 委托對象
委托類的要求:
- 對于
val
(只讀屬性),需要實現getValue()
; - 對于
var
(可變屬性),需要實現getValue()
和setValue()
常見的使用場景:
- 延遲初始化:
by lazy
(首次訪問時才進行初始化); - 屬性監聽:
Delegates.observable
(屬性值發生變化時觸發回調); - 動態屬性存儲:從
Map
中讀取屬性(如解析 JSON 或配置);
示例:
class Person(val name: String, val age: Int)val person: Person by lazy {Person("Eileen", 34)
}var name: String by Delegates.observable("init data") { prop, old, new ->println("${prop.name} 從 $old 變為 $new")
}class Student(val map: Map<String, Any>) {val name: String by map // 從 map 中按 key 取值val age: Int by map
}val student = Student(mapOf("name" to "Eileen", "age" to 30))
println(student.name) // Eileen
Kotlin 標準庫提供的委托工具:
lazy
:延遲初始化;Delegates.observable
:監聽屬性變化;Delegates.vetoable
:在賦值前校驗值是否合法;Delegates.notNull
:非空屬性的延遲賦值;
2 類委托
定義:將類的接口實現委托給另一個對象,實現組合復用。 通過組合代替繼承,避免單繼承的局限性。
語法:
class 類名(委托對象): 接口 by 委托對象
典型場景:
- 裝飾器模式:增強對現有對象的功能(如添加日志、緩存);
- 接口實現復用:多個類共享同一接口的默認邏輯;
- 動態替換行為:運行時切換委托對象(如策略模式);
示例:
interface DataFetcher {fun fetchData(): String
}class NetworkFetcher : DataFetcher {override fun fetchData() = "從網絡獲取數據"
}// 通過委托添加緩存功能
class CachedFetcher(private val fetcher: DataFetcher) : DataFetcher by fetcher {private var cachedData: String? = nulloverride fun fetchData(): String {return cachedData ?: fetcher.fetchData().also { cachedData = it }}
}fun main() {val networkFetcher = NetworkFetcher()val cachedFetcher = CachedFetcher(networkFetcher)println(cachedFetcher.fetchData()) // 第一次調用從網絡獲取println(cachedFetcher.fetchData()) // 第二次直接返回緩存
}