Kotlin 对象枚举委托

Posted Lucky_William

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin 对象枚举委托相关的知识,希望对你有一定的参考价值。

一、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

以上是关于Kotlin 对象枚举委托的主要内容,如果未能解决你的问题,请参考以下文章

kotlin 委托

kotlin委托工厂map存储属性值

Kotlin常用的 Kotlin 类 ② ( 枚举类 | 枚举类定义函数 | 密封类 )

Kotlin常用的 Kotlin 类 ② ( 枚举类 | 枚举类定义函数 | 密封类 )

kotlin中委托的概念和原理

将接口从片段传递到kotlin中的活动