当前位置: 首页 > news >正文

Kotlin 内联函数语法之let、apply、also、run、with的用法与详解

一、介绍

kotlin的语法千奇百怪,今天我们将介绍项目中频率使用比较高的几个内联函数。

二、什么叫内联函数?

内联函数 的语义很简单:把函数体复制粘贴到函数调用处 。使用起来也毫无困难,用 inline关键字修饰函数即可。

语法:

inline fun 函数名(){
}

介绍:

        在正常定义的函数最前面通过inline修饰一下,不管你在哪里调用了内联函数,该函数体内的方法都会被插入到调用出。

实战与分析:

class TestInline {inline fun log(msg: String) {System.out.println("show log=${msg}")}fun printLog() {log("I am working")}
}fun main() {val  tt=TestInline()tt.log("aaaa")}

kotlin编译后的结果:

 

 

分析:

        通过kotlin的源码与翻译后的对比发现,只要调用了内联函数,内联函数体的代码会被复制到调用处。

        通过以上对比我们大概了解到内联函数的作用,其实对于我的分析,如果内联函数体很大,被到处引用,就会编译出特别多的多余代码,这个方式与方法的抽取调用有什么好处?目前我并没有发现这种方式的特别之处,唯一的好处就是在kotlin译码后,在结果中更方便阅读。

三、高频常用let、apply、also、run、with的介绍与使用

let、apply、also、run、with都是内联函数,但是通过使用有所不同,接下来我们做详细的分析与介绍

1、let

@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}return block(this)
}

从源码中可以分析,有两个泛型,一个是自身,一个是结果

所以在调用返回值传的是this,自身,返回值可以是任意类型。常见的用法就是通过对象

aa?.let这种执行。

常用的两种:

1.需要用到对象自身aa?.let{},免去对变量的判空

    var aa: String? = "text-"//创建TestKKK对象,aa作为变量复制,返回ttval aaa = aa.let {val tt=TestKKK()tt.name=ittt}//返回aa的长度val length=aa?.let {it.length}

2.apply

public inline fun <T> T.apply(block: T.() -> Unit): T {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}block()return this
}

apply的用法是返回调用参数类型一样的变量。

常见的用法:

1.初始化

    tt?.apply {tt = TestKKK()tt!!.name = "nodify"tt}

2.修改变量参数

    tt?.apply {tt!!.name = "nodify"tt}

3.also

public inline fun <T> T.also(block: (T) -> Unit): T {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}block(this)return this
}

also的语法和apply使用类似,在block高阶函数中接受自己,但是,block不接受返回值,也就是说,你无法通过also去做初始化的工作。如果一个对戏是null,那么在使用also的使用,会报空指针

    var talso: TestKKK? = nulltalso=talso?.also {talso=TestKKK()talso!!.name = "0000"talso}Log.log("also=${talso!!.name}")

 所以,也就是说,变量自身的内存地址不接受also体修改,also只能修改变量的属性。

4.run

public inline fun <T, R> T.run(block: T.() -> R): R {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}return block()
}

run的用法比较随意。它返回任意类型,即使自身为null也可以执行返回结果。

    var trun: TestKKK? = nullval run1 = trun.run {"Hello"}Log.log("run1 is String=${run1}")
    val run2 = trun.run {trun = TestKKK()trun!!.name = "run"trun}Log.log("run2 is TestKKK=${run2!!.name}")

返回类型取决于block代码快最后一行的参数,如果最后一行有返回值就是该返回的类型

5.with

public inline fun <T, R> with(receiver: T, block: T.() -> R): R {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}return receiver.block()
}

with的用法是接受一个参数,然后返回任性参数类型。接受的参数将会是block函数体的参数。

    val with = with(run3) {run2.name = run3.toString()run2}Log.log("with is TestKKK=${with.name}")

四、总结

        通过以上的学习,从一开始的内联函数是什么到如何定义,以及译码后函数体的变化,都做了一次普及。最后就是我们常见的let、apply、also、run、with语法使用。

        这里特别注意的是also的用法,由于also无法在block体做对象的初始化工作,所以在工作中,尽量少使用block,避免出现空指针。

        如果需要初始化,可以使用apply,如果使用当前变量返回任意类型使用with、run与let。

apply:不要使用?去做空的拦截,特别在出初始化,否则初始化永远都不会执行

五、返回类型

1.返回自身的:apply与also,返回this,但是also如果是null,返回就是null,即使你在block初始化也没用

2.其他返回类型取决于block的最后一行代码,如果最后一行是变量、或者属性的get或者方法有返回值,那么久有返回值,否则为unit。

http://www.lryc.cn/news/99116.html

相关文章:

  • Swift 中如何判断是push 过来的页面 还是present过来的 页面
  • 基于K8s环境·使用ArgoCD部署Jenkins和静态Agent节点
  • 874. 模拟行走机器人
  • 【Linux】- RPM 与 YUM
  • Visual Studio 2015编译器 自动生成 XXX_EXPORTS宏
  • HTML5的应用现状与发展前景
  • day44-Spring_AOP
  • selenium IDE 接入jenkins-转载
  • 云计算结合数据科学突破信息泛滥(下)
  • 蓝桥杯单片机第十二届国赛 真题+代码
  • MyBatis学习笔记之缓存
  • ​小程序 WxValidate.js ​再次封装
  • redis 第三章
  • MYSQL常见面试题汇总
  • Java接口通过token登录实现页面跳转到登录成功后的页面
  • Linux-文件管理
  • Android getevent用法详解
  • 面试题-TS(二):如何定义 TypeScript 中的变量和函数类型?
  • 【4】-多个User执行测试
  • 基于Eisvogel模板的Markdown导出PDF方法
  • linux服务器安装redis
  • QT中信号和槽本质
  • layui各种事件无效(例如表格重载或 分页插件按钮失效)的解决方法
  • flutter开发实战-父子Widget组件调用方法
  • 策略模式的实现与应用:掌握灵活算法切换的技巧
  • 当ChatGPT应用在汽车行业,具体有哪些场景?
  • 行为型-中介者模式(Mediator Pattern)
  • Kibana+Prometheus+node_exporter 监控告警部署
  • 【前端知识】JavaScript——设计模式(工厂模式、构造函数模式、原型模式)
  • 未来的算法备案法规:创新和安全如何兼顾?