目錄
- 一、Kotlin 物件
- 1. kotlin 伴生物件
- 2. kotlin 物件和單例模式
- 二、Kotlin 列舉
- 1. kotlin 定義列舉
- 2. kotlin 使用列舉
- 三、Kotlin 委托
- 1. kotlin 類委托
- 2. kotlin 屬性委托
- 3. kotlin Map 委托
- 4. kotlin 延遲屬性
- 5. kotlin 屬性監聽
- 附 Github 原始碼
一、Kotlin 物件
1. kotlin 伴生物件
class Demo {
val field: String = "demo field"
// kotlin 定義伴生物件
companion object {
// kotlin 定義常量
const val KEY_NAME = "key_name"
// kotlin 模擬靜態方法
@JvmStatic // 加注解實作和 java 中使用靜態方法相同效果
fun method() {
println("invoke companion method")
}
}
}
fun main() {
// kotlin 可以使用外部類的類名直接呼叫伴生物件的屬性或方法
Demo.KEY_NAME
Demo.method()
}
2. kotlin 物件和單例模式
fun main() {
// 使用 object 宣告物件運算式
val runnable = object : Runnable {
override fun run() {
println("run in Runnable")
}
}
// 同上,lambda 簡寫形式
val runnable2 = Runnable {
println("run in Runnable lambda")
}
// 使用物件運算式
Thread(runnable).start()
Thread(runnable2).start()
// 呼叫單例類的屬性和方法
println(DemoManager.field)
DemoManager.method()
}
/**
* 使用 object 定義單例類
*/
object DemoManager {
var field = "string value"
fun method() {
println("invoke method")
}
}
二、Kotlin 列舉
1. kotlin 定義列舉
enum class Week(val text: String = "") {
Monday("星期一"),
Tuesday("星期二"),
Wednesday("星期三"),
Thursday("星期四"),
Friday("星期五"),
Saturday("星期六"),
Sunday("星期日")
}
2. kotlin 使用列舉
fun main() {
// 構造列舉
val tuesday = Week.valueOf("Tuesday")
// 訪問列舉常量的名稱,與在其列舉宣告中宣告的完全相同,
println(tuesday.name) // Tuesday
// 回傳此列舉常量的序數(它在列舉宣告中的位置,其中初始常量被分配零序數)
println(tuesday.ordinal) // 1
// 回傳此列舉型別的常量的陣列
println(Week.values().contentToString()) // [Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday]
// 訪問列舉
val week: Week = Week.Monday
when (week) {
Week.Monday -> println(week.name) // Monday
Week.Tuesday -> println(week.name)
Week.Wednesday -> println(week.name)
Week.Thursday -> println(week.name)
Week.Friday -> println(week.name)
Week.Saturday -> println(week.name)
Week.Sunday -> println(week.name)
}
}
三、Kotlin 委托
1. kotlin 類委托
/**
* 定義介面
*/
interface Factory {
fun produce()
}
/**
* 美食工廠,實作工廠的方法
*/
class FoodFactory : Factory {
override fun produce() {
println("生產美食")
}
}
/**
* Agent1 實作了 Factory 介面,但委托給 FoodFactory 去實作
*/
class Agent1(factory: FoodFactory) : Factory by factory
/**
* Agent2 實作了 Factory 介面,但委托給 FoodFactory 去實作,重寫了介面定義的方法
*/
class Agent2 : Factory by FoodFactory() {
override fun produce() {
println("Agent2 自己 生產美食")
}
}
fun main() {
// 類委托
val agent1 = Agent1(FoodFactory())
agent1.produce() // 生產美食
val agent2 = Agent2()
agent2.produce() // Agent2 自己 生產美食
}
2. kotlin 屬性委托
提供和 ReadOnlyProperty 或 ReadWriteProperty 介面相同簽名的方法即可實作屬性委托
/**
* 定義屬性委托
*/
class FieldDemo {
var name: String by FieldDelegate()
}
/**
* 屬性委托類,提供和 ReadOnlyProperty 或 ReadWriteProperty 介面相同簽名的方法即可實作屬性委托
*/
class FieldDelegate {
private var fieldValue = "default str"
operator fun getValue(thisRef: FieldDemo, property: KProperty<*>): String {
println("獲取 ${thisRef.javaClass.simpleName} 的屬性 ${property.name} 值")
return fieldValue
}
operator fun setValue(thisRef: FieldDemo, property: KProperty<*>, value: String) {
println("設定 ${thisRef.javaClass.simpleName} 的屬性 ${property.name} 值:$value")
fieldValue = value
}
}
fun main() {
// 屬性委托
val fieldDemo = FieldDemo()
fieldDemo.name = "test field delegate" // 設定 FieldDemo 的屬性 name 值:test field delegate
println(fieldDemo.name) // 獲取 FieldDemo 的屬性 name 值
}
3. kotlin Map 委托
- kotlin 在 MapAccessors 類中給 Map 定義了和 ReadOnlyProperty 介面相同簽名的方法,可以用于只讀屬性的委托,
- kotlin 在 MapAccessors 類中給 MutableMap 定義了和 ReadWriteProperty 介面相同簽名的方法,可以用于讀寫屬性的委托,
/**
* 只讀屬性可以委托給 Map
* 類只需要對外暴露 map 即可
*/
class DelegateMap(val map: Map<String, Any?>) {
val key1: Int by map
val key2: String by map
val key3: Boolean by map
}
/**
* 讀寫屬性可以委托給 MutableMap
* 類只需要對外暴露 map 即可
*/
class DelegateMutableMap(val map: MutableMap<String, Any?>) {
var key1: Int by map
var key2: String by map
var key3: Boolean by map
}
fun main() {
// 只讀屬性對外暴露 Map
val delegate1 = DelegateMap(mapOf("key1" to 1, "key2" to "str", "key3" to true))
// 相當于呼叫 ReadOnlyProperty 的 getValue 方法
println(delegate1.key1)
println(delegate1.key2)
println(delegate1.key3)
val map = delegate1.map
println(map["key1"])
println(map["key2"])
println(map["key3"])
// 讀寫屬性對外暴露 MutableMap
val delegate2 = DelegateMutableMap(mutableMapOf())
// 相當于呼叫 ReadWriteProperty 的 setValue 方法
delegate2.key1 = 100
delegate2.key2 = "key2 value"
delegate2.key3 = false
val mutableMap = delegate2.map
println(mutableMap["key1"])
println(mutableMap["key2"])
println(mutableMap["key3"])
}
4. kotlin 延遲屬性
- 當延遲屬性被訪問的時候才會執行 lambda 運算式初始化值
- 只會執行一次 lambda 運算式,隨后會獲取第一次的值直接回傳
// 延遲屬性:只會獲取一次 lambda 運算式的值,后續會使用第一次獲取的值直接回傳
val lazyField: String by lazy {
println("執行 lambda 運算式")
"this is a lazy field"
}
// 傳入策略,使用鎖用于確保只有單個執行緒可以初始化Lazy實體,
val lazyField2: String by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
"this is a lazy field"
}
fun main() {
// 只會列印一次 "執行 lambda 運算式"
println(lazyField)
println(lazyField)
}
5. kotlin 屬性監聽
/**
* 屬性監聽,總是能賦值成功
*/
var observerField1: String by Delegates.observable("default") { property, oldValue, newValue ->
println("$property 的 oldValue: $oldValue, newValue: $newValue")
}
/**
* 屬性監聽,符合條件 新值大于 0,才能成功賦值
*/
var observerField2: Int by Delegates.vetoable(0) { property, oldValue, newValue ->
println("$property 的 oldValue: $oldValue, newValue: $newValue")
newValue > 0
}
fun main() {
observerField1 = "set new value" // 列印:kotlin.String 的 oldValue: default, newValue: set new value
observerField2 = 1 // 列印:kotlin.Int 的 oldValue: 0, newValue: 1
observerField2 = -1 // 列印:kotlin.Int 的 oldValue: 1, newValue: -1,此處會設定失敗,需要大于0才能設定成功
println(observerField2) // 列印:1
}
附 Github 原始碼
Companion&Object&Enum&Delegate&Lazy.kt
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/374836.html
標籤:其他
上一篇:Kotlin 例外處理
