kotlin中委托的概念和原理(代码片段)

author author     2023-02-09     690

关键词:

kotlin中委托的概念和原理

问题背景

kotlin的日常使用过程中,经常会使用到委托机制,问题来了,委托机制究竟是什么呢? 委托模式:多个对象接收并处理同一请求,他们将请求委托给另一个对象统一处理请求。 比如调用A类的methodA方法,其实背后是B类的methodB去执行。

问题分析

Kotlin 的委托机制在语言层面自动实现了类似 Java 的组合代理。Kotlin 的委托包括委托类、委托属性,使用 by 关键字表示委托。

1、类委托

(1)假设有一个 Db接口和一个GreenDaoDb类,用来保存数据。代码如下:

interface Db 
    fun save()

GreenDaoDb类

class GreenDaoDb : Db 
    override fun save() 
        println("green dao db save()")
    

(2)如果使用 Java 风格的委托方式,可能会这么写,代码如下:

class MyDb(private val db: Db) : Db 
    override fun save() 
        db.save()
    


代码分析: 这种方式有很多样板代码,比如重写 save(),在接口方法调用属性 db 的 save(),类似于很多时候java的代理模式使用的样板代码。 (3)上面的java风格的委托方式,如果使用kotlin的委托机制,可以怎么实现呢?代码如下:

class UniversalDb(db: Db) : Db by db

Db 接口的所有方法都交给 by 关键字后面的 db 实现。 另外,如果我们要对某个方法进行重新实现或者新增,只需要单独重写那一个方法就可以了,其他的方法仍然可以享受类委托所带来的便利,如下所示:

class UniversalDb(db: Db) : Db by db 
  
    fun helloWorld() = println("Hello World")


由上面可以看出,类委托的核心思想是将一个类的具体实现委托给另一个类去完成。

2、委托属性

对应的,委托属性的核心思想是将一个属性(字段)的具体实现委托给另一个类去完成。 委托属性的语法结构,代码如下:

class MyTest 
    // 属性代理的语法结构
    var p by Delegate()

实现Delegate类,代码如下:

class MyClass 
    var p by Delegate()


class Delegate 
    var propValue: Any? = null

代码提示报错,如下图所示: 修改委托类Delegate代码如下:

import kotlin.reflect.KProperty

class MyTest 
    var p by Delegate()


class Delegate 
    var propValue: Any? = null

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

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

分析可知,在Delegate类中我们必须实现getValue()和setValue()这 两个方法,并且都要使用operator关键字进行声明。 getValue()方法要接收两个参数:第一个参数用于声明该Delegate类的委托功能可以在什么类中使用,这里写成MyTest表示仅可在MyTest类中使用;第二个参数KProperty<*>是 Kotlin中的一个属性操作类,可用于获取各种属性相关的值,在当前场景下用不着,但是必须在方法参数上进行声明。

setValue()方法也是相似的,只不过它要接收3个参数。前两个参数和getValue()方法是相 同的,最后一个参数表示具体要赋值给委托属性的值,这个参数的类型必须和getValue()方法返回值的类型保持一致。

3、懒加载委托

Kotlin通过by关键字就可以实现委托的效果,比如的by lazy ,其实就是利用委托实现的延迟初始化语法。 以下是它的使用:

val p by lazy 
    print("12345")
    123456

这里使用了一种懒加载技术,把想要延迟执行的代码放到by lazy代码块中,这样代码块中的代码在一开始的时候就不会执行,只有当laziness变量首次被调用的时候,代码块中的代码才会执行,代码如下:

val p by lazy 
    println("00000")
    123456


fun main() 
    // lazy delegate
    println("lazy delegate beging")
    println(p)
    println(p)

运行结果如下: 有结果可知,第一次 println(p) 会打印 “00000”,而第二次不会。因为使用 lazy 方法将 request 的结果保存,第二次打印 data 时,直接返回 reqeust 结果,而不是再次执行 request。 查看lazy方法的源码如下: ....../kotlin/util/LazyJVM.kt:21: kotlin.SynchronizedLazyImpl: 有源码可知,SynchronizedLazyImpl 实现了一个单例模式,如果 _value 初始化过,直接返回 _value 的值,否则使用 lazy 的入参函数 initializer 初始化,返回 T 类型的值,并赋值给 _value。

问题总结

本文对kotlin中的委托机制进行了一个初步的介绍,包括类委托、属性委托,同时对lazy延迟初始化关键字进行了一个简单的介绍,有兴趣的同学可以进一步深入学习。

深入理解委托——为什么c#要引入委托(代码片段)

...什么的?在正式介绍委托之前,我想下看看生活中委托的例子——生活中,如果如果我们需要打官司,在法庭上是由律师为我们辩护的,然而律师真真执行的是当事人的陈词,这时候律师就是一个委托对象... 查看详情

关于c#中委托的多播应用问题

下面那个委托多播调用结果为什么是75啊!!没想明白,不应该是65吗??nc(5);//调用的时候不是分别将5传给AddNum()和MultNum(),分别得到15和50,再相加吗,就等于65啊!!本人菜鸟一枚。望得大神赐教!!!usingSystem;delegateintNumberChang... 查看详情

XCode(iOS)中委托的自动导入回调

】XCode(iOS)中委托的自动导入回调【英文标题】:AutoimportcallbacksofdelegateinXCode(iOS)【发布时间】:2010-10-1322:07:05【问题描述】:因为倾斜是可能的自动导入,或者xcode中有一个选项允许导入委托的所有回调(如MKMapviewdelegate或其... 查看详情

kotlin中闭包的概念和原理(代码片段)

kotlin中闭包的概念和原理问题背景安卓开发,kotlin学习和使用过程中,kotlin闭包肯定算是个新概念,尤其从安卓java开发转kotlin的同学,现在一起看看kotlin的闭包到底是什么意思?闭包的概念关键:外部函数调用之后其变量对象... 查看详情

kotlin的拓展函数和原理(代码片段)

kotlin的拓展函数和原理问题背景kotlin的使用过程中有个拓展函数的概念,这个概念在java中是没有的,那么问题来了,kotlin中拓展函数是什么呢?拓展函数的概念:不改变原有类的情况下,增加新的方法,扩展新的功能。下面一... 查看详情

c#中委托的作用是啥?

使用委托的作用:使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。与C或C++中的函数指针不同,委托是面向对象,而且是类型安全的。... 查看详情

.net中委托的解析泛型解析可变性解析表达式和匿名方法基invoke的用法()

委托解析:http://www.cnblogs.com/DeepLearing/p/4594518.html.net泛型解析(上)http://www.cnblogs.com/DeepLearing/p/4554867.html#3211258.net可变性解析:http://www.cnblogs.com/DeepLearing/p/4592759.html.netLambda表达式和匿名方法:http://www.cnblogs.co... 查看详情

kotlin-协程基础及原理(代码片段)

初识协程什么是协程Kotlin1.3添加了协程Coroutine的概念,文档中介绍协程是一种并发设计模式,可以在Android平台上使用它来简化异步执行的代码。协程具有如下特点:异步代码同步化:使用编写同步代码的方式编写... 查看详情

kotlin异步|flow应用场景及原理(代码片段)

什么是“异步数据流”?它在什么业务场景下有用武之地?它背后的原理是什么?读一读Flow的源码,尝试回答这些问题。同步&异步&连续异步同步和异步是用来形容“调用”的:同步调用:当调用发... 查看详情

kotlin协程协程的挂起和恢复①(协程的挂起和恢复概念|协程的suspend挂起函数)(代码片段)

文章目录一、协程的挂起和恢复概念二、协程的suspend挂起函数一、协程的挂起和恢复概念函数最基本的操作是:调用call:通过函数名或函数地址调用函数;返回return:函数执行完毕后,继续执行函数调用的下一行代码;协程在调用call和... 查看详情

kotlin协程协程的挂起和恢复①(协程的挂起和恢复概念|协程的suspend挂起函数)(代码片段)

文章目录一、协程的挂起和恢复概念二、协程的suspend挂起函数一、协程的挂起和恢复概念函数最基本的操作是:调用call:通过函数名或函数地址调用函数;返回return:函数执行完毕后,继续执行函数调用的下一行代码;协程在调用call和... 查看详情

kotlin协程之flow工作原理(代码片段)

概述最近想学习一下Kotlin中flow的用法,Google上搜了搜发现很多比较RxJava和flow的文章,其实我在实际业务中从来没有用过RxJava,倒不是因为它不好,而是…我一直傻傻不太会用RxJava的操作符,看不太懂,又一直没花时... 查看详情

html道格拉斯希波利托的钢笔。(代码片段)

查看详情

深入kotlin-伴生对象和扩展(代码片段)

伴生对象在kotlin中,类没有static方法的概念,这与java不同。kotlin用package级别的函数来取代静态方法(在字节码层级,这就是静态方法)。所谓伴生对象其实就是位于class中的object,使用companionobject关键字... 查看详情

算法系列之--javascript和kotlin的堆排序算法(原)(代码片段)

上一节我们学习了希尔排序算法,这一节来学习堆排序算法,算法系列文章目录在这里。介绍    堆排序算法是基于堆这种数据结构设计的算法,理解了堆的概念就明白了堆算法的原理,因此我们简单介绍一下... 查看详情

zuul的概念和原理(代码片段)

 https://zhuanlan.zhihu.com/p/80372029 一、zuul是什么zuul是netflix开源的一个APIGateway服务器,本质上是一个webservlet应用。Zuul在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架。Zuul相当于是设备和Netflix流应用的Web网站... 查看详情

kotlin中的varval和const(代码片段)

1.首先明确概念var:variable,变量。val:value,值(Kotlin官方文档中称为immutablevariable,不可变变量)。const:常量2.用法因为var和val区别很大,所以这里只介绍const的用法。2.1语法constval常量值的名字=常量值const只能用来修饰val。... 查看详情

kotlin之包(代码片段)

在kotlin中包的概念在表达方式上与Java完全一样,不过kotlin中的包和目录没有关系,kotlin包仅仅是为了引用文件中的资源而设计的。packageloaderman.barfunprogress()print("输出文字")packageloadermanimportloaderman.bar.progressfunmain(arg:Array<String>... 查看详情