Kotlin学习4—委托与lazy函数

前言

委托是一种设计模式,基本理念是:操作对象自己不会去处理某段逻辑,而是会把工作委托给另外一个辅助对象去处理

简单的委托模式的例子如下,实现Set接口,实现一个自己的实现类,里面借助HashSet这个辅助对象来实现,如下代码:

    class MySet<T>(val helpSet: Set<T>) : Set<T> {
        override val size: Int
            get() = helpSet.size

        override fun contains(element: T): Boolean {
            return helpSet.contains(element)
        }

        override fun containsAll(elements: Collection<T>): Boolean {
            return helpSet.containsAll(elements)
        }

        override fun isEmpty(): Boolean {
            return helpSet.isEmpty()
        }

        override fun iterator(): Iterator<T> {
            return helpSet.iterator()
        }
    }

为啥既然调用的都是辅助对象的方法,不干脆直接使用辅助对象?因为如果我们只是让大部分的方法实现调用辅助对象的方法,少部分的方法由自己重写实现,那么这就体现了委托模式的精妙之处

在Kotlin中,支持委托功能,分为两种:类委托和委托属性

类委托

核心思想:将一个类的具体实现委托给另一个类去完成

Kotlin中的委托使用的关键字是by,只需要在接口声明后面使用by,再接上受委托的辅助对象即可

    class MySet1<T>(val helpSet: Set<T>) : Set<T> by helpSet {
         fun hello() = print("hello")
    }
委托属性

核心思想:将一个属性(字段)的具体实现委托给另一个类去实现

委托属性的语法结构,标准模板如下:

    class MyClass {
        var temp by Delegate()
    }

    class Delegate {
        var propValue: Any? = null

        operator fun getValue(myClass: MyClass, prop: KProperty<*>): Any? {
            return propValue
        }

        operator fun setValue(myClass: MyClass, prop: KProperty<*>, value: Any?) {
            propValue = value
        }
    }

上述写法代表着将temp属性的具体实现委托给Delegate类去完成,当调用temp属性的时候会自动调用Delegate类的getValue()方法,当给temp属性赋值的时候会调用Delegate类的setValue()方法

在Delegate类中必须实现getValue()和setValue()这两个方法,并且要使用operator关键字进行声明

关于Delegate类中的写法,拿getValue()方法来进行说明:第一个参数用于声明该Delegate类的委托功能可以在什么类中使用;第二个参数KProperty<*>是Kotlin中的一个属性操作类,可用于获取各种属性相关的值,当前场景用不到,<*>这种泛型的写法表示是不关心的具体类型,只是为了通过编译而已,类似Java中的<?>写法

有种特殊的场景,当temp属性被定义成常量val修饰时,是不需要实现setValue()方法的,意味着该属性无法修改其值:

    class MyClass {
        val temp2 by Delegate2()
    }

    class Delegate2 {
        var propValue: Any? = null

        operator fun getValue(myClass: MyClass, prop: KProperty<*>): Any? {
            return propValue
        }
    }
    
lazy函数

可以把需要延迟的函数放在by lazy 代码块中,这块代码在一开始的时候是不回执行的,只有当调用的时候才会执行,实际上,by lazy并不是连在一起的关键字,只有by才是Kotlin的关键字,lazy只是一个高阶函数而已

在lazy函数中会创建并返回一个Delegate对象,当调用该对象时,其实调用的是Delegate对象的getValue()方法,然后getValue()方法中又会调用lazy函数传入Lambda表达式

接下里手动实现一个lazy函数,创建个Later.kt文件,编写代码如下:

    class Later<T>(val block: () -> T) {
        var value: Any? = null

        operator fun getValue(any: Any?, prop: KProperty<*>): T {
            if (null == value) {
                value = block
            }
            return value as T
        }
    }

为了方便使用,使其的用法更加类似于lazy函数,在Later.kt文件中再定义一个顶层函数:

    // 定义一个顶层方法
    fun <T> later(block: () -> T) = Later<T>(block)

当使用Later时:

    class MyClass {
        val temp3 by later { 

        }
    }

注意:
在正式项目中,要使用懒加载函数的话,可以使用Kotlin内置的lazy函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值