转自:https://blog.csdn.net/guijiaoba/article/details/54615036

Kotlin之let,apply,with,run函数区别


重新整理

重新整理了各种函数的区别,请移步到这里


以下作废


很长一段时间内都一直使用Kotlin这门语言,也只是纯粹使用简单语法,最近有时候写的代码,编辑器自动提示使用let等函数,然后就专门花点时间研究了下。

let

首先let()的定义是这样的,默认当前这个对象作为闭包的it参数,返回值是函数里面最后一行,或者指定return

fun <T, R> T.let(f: (T) -> R): R = f(this)
  • 1

简单示例:

fun testLet(): Int {
// fun <T, R> T.let(f: (T) -> R): R { f(this)}
"testLet".let {
println(it)
println(it)
println(it)
return 1
}
}
//运行结果
//testLet
//testLet
//testLet
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

可以看看最后生成的class文件,代码已经经过格式化了,编译器只是在我们原先的变量后面添加了let里面的内容。

public static final int testLet() {
String str1 = "testLet";
String it = (String)str1;
int $i$a$1$let;
System.out.println(it);
System.out.println(it);
System.out.println(it);
return 1;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

来个复杂一定的例子

fun testLet(): Int {
// fun <T, R> T.let(f: (T) -> R): R { f(this)}
"testLet".let {
if (Random().nextBoolean()) {
println(it)
return 1
} else {
println(it)
return 2
}
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

编译过后的class文件

public static final int testLet() {
String str1 = "testLet";
String it = (String)str1;
int $i$a$1$let;
if (new Random().nextBoolean())
{
System.out.println(it);
return 1;
}
System.out.println(it);
return 2;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

apply

apply函数是这样的,调用某对象的apply函数,在函数范围内,可以任意调用该对象的任意方法,并返回该对象

fun <T> T.apply(f: T.() -> Unit): T { f(); return this }
  • 1

代码示例

fun testApply() {
// fun <T> T.apply(f: T.() -> Unit): T { f(); return this }
ArrayList<String>().apply {
add("testApply")
add("testApply")
add("testApply")
println("this = " + this)
}.let { println(it) }
} // 运行结果
// this = [testApply, testApply, testApply]
// [testApply, testApply, testApply]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

编译过后的class文件

  public static final void testApply()
{
ArrayList localArrayList1 = new ArrayList();
ArrayList localArrayList2 = (ArrayList)localArrayList1;
int $i$a$1$apply;
ArrayList $receiver;
$receiver.add("testApply");
$receiver.add("testApply");
$receiver.add("testApply");
String str = "this = " + $receiver;
System.out.println(str);
localArrayList1 = localArrayList1;
ArrayList it = (ArrayList)localArrayList1;
int $i$a$2$let;
System.out.println(it);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

with

with函数是一个单独的函数,并不是Kotlin中的extension,所以调用方式有点不一样,返回是最后一行,然后可以直接调用对象的方法,感觉像是let和apply的结合。

fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
  • 1

代码示例:

fun testWith() {
// fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
with(ArrayList<String>()) {
add("testWith")
add("testWith")
add("testWith")
println("this = " + this)
}.let { println(it) }
}
// 运行结果
// this = [testWith, testWith, testWith]
// kotlin.Unit
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

class文件

 public static final void testWith()
{
Object localObject = new ArrayList();
ArrayList localArrayList1 = (ArrayList)localObject;
int $i$a$1$with;
ArrayList $receiver;
$receiver.add("testWith");
$receiver.add("testWith");
$receiver.add("testWith");
String str = "this = " + $receiver;
System.out.println(str);
localObject = Unit.INSTANCE;
Unit it = (Unit)localObject;
int $i$a$2$let;
System.out.println(it);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

run

run函数和apply函数很像,只不过run函数是使用最后一行的返回,apply返回当前自己的对象。

fun <T, R> T.run(f: T.() -> R): R = f()
  • 1

代码示例

fun testRun() {
// fun <T, R> T.run(f: T.() -> R): R = f()
"testRun".run {
println("this = " + this)
}.let { println(it) }
}
// 运行结果
// this = testRun
// kotlin.Unit
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

class文件

  public static final void testRun()
{
Object localObject = "testRun";
String str1 = (String)localObject;
int $i$a$1$run;
String $receiver;
String str2 = "this = " + $receiver;
System.out.println(str2);
localObject = Unit.INSTANCE;
Unit it = (Unit)localObject;
int $i$a$2$let;
System.out.println(it);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

总结

怎么样,是不是看晕了,没关系,我们来总结下。

函数名 定义 参数 返回值 extension 其他
let fun T.let(f: (T) -> R): R = f(this) it 闭包返回  
apply fun T.apply(f: T.() -> Unit): T { f(); return this } 无,可以使用this this  
with fun with(receiver: T, f: T.() -> R): R = receiver.f() 无,可以使用this 闭包返回 调用方式与其他不同
run fun T.run(f: T.() -> R): R = f() 无,可以使用this 闭包返回

Kotlin之let,apply,with,run函数区别(转)的更多相关文章

  1. [Java] Thread的start()和run()函数区别

    1.start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码: 通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状 ...

  2. Kotlin 之 let、with、run、apply、also 函数的使用

    一.内联拓展函数 let let 扩展函数的实际上是一个作用域函数,当你需要去定义一个变量在一个特定的作用域范围内,let函数的是一个不错的选择:let函数另一个作用就是可以避免写一些判断null的操 ...

  3. 瞬间记住Javascript中apply与call的区别

    关于Javascript函数的apply与call方法的用法,网上的文章很多,我就不多话了.apply和call的作用很相似,但使用方式有区别 apply与call的第一个参数都是一个对象,这个对象就 ...

  4. 改变this指针的apply,call,bind的区别

    apply.call 在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向. Jav ...

  5. apply()和call()的区别

    这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值. apply()接收两个参数:一个参数是在其中运行的作用域,另一个是参数数组(可以是Array实例,也可以是arg ...

  6. 【JavaScript】apply和call的区别在哪?

    我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这里我做如下笔记,希望和大家 ...

  7. android SharedPreferences apply和commit的区别

    1.apply没有返回值而commit返回boolean表明修改是否提交成功2.apply是将修改数据原子提交到内存, 而后异步真正提交到硬件磁盘, 而commit是同步的提交到硬件磁盘3.apply ...

  8. JavaScript之apply()和call()的区别

    我 在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示 例,总算是看的有点眉目了,在这里我做如下笔记,希望和 ...

  9. JS 中的this指向问题和call、apply、bind的区别

    this的指向问题 一般情况下this对象指向调用函数的对象,全局环境中执行函数this对象指向window. function a(){ console.log(this); //输出函数a中的th ...

随机推荐

  1. MySQLdb-python安装

    安装很简单,步骤如下: 前期:yum -y install python-setuptools,或者自己网上找源码包安装 1. 下载安装包: #wget  https://pypi.python.or ...

  2. 接口需要上一个接口的返回值(unittest)

    import unittest,requests ''' 使用unittest框架的时候,这个接口需要上一个接口的返回值 ''' class Test_case(unittest.TestCase): ...

  3. 前端每日实战:67# 视频演示如何用纯 CSS 创作单元素点阵 loader

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览.https://codepen.io/comehope/pen/YvBvBr 可交互视频 此视频是可以 ...

  4. 终极解决方案: Invalid character found in the request target.

    终极解决方案:(导出可能出现) 我的tomcat版本是8.5.32,导出时遇到以下报错. 报错日志: Invalid character found in the request target. Th ...

  5. 系统信息&&硬件信息查看

    系统信息&&硬件信息查看 一系统信息查看 (一)查看系统版本信息 [root@centos7 ~]# cat /etc/redhat-release CentOS Linux rele ...

  6. FMXUI TEXTVIEW代码设置IMAGEINDEX

    FMXUI作为一个开源的控件,真是DELPHIER的福音,向作者致敬.​TEXTVIEW非常好用,在属性面板中有ImageIndex属性,可以方便设置图标,在实际应用中图标状态需要改变,但在代码设置时 ...

  7. spring-boot 定时任务案例

    1.运行环境 开发工具:intellij idea JDK版本:1.8 项目管理工具:Maven 4.0.0 2.Maven Plugin管理 pom.xml配置代码: <?xml versio ...

  8. Vue使用的扩展

    1.Bus(总线)实现非父子组件通信 Vue2.0提供了Vuex进行非父子组件之间的通信,但在简单的场景下,可以使用一个空的Vue实例作为中央事件总线. 实现代码示例: <div id=&quo ...

  9. vue开发微信公众号--开发准备

    由于工作项目的原因,需要使用vue开发微信公众号,但是这种微信公众号更多是将APP套了一个微信的壳子,除了前面的授权和微信有关系以外,其他的都和微信没多大的关系了,特此记录 开发流程 首先需要在电脑上 ...

  10. 重温HTML和CSS3

    重温Web前端基础 本篇幅中着重文字,只是记录一些自己的见解,巩固下自身基础 网页结构是什么? 结构层 html 导航,列表,段文字,图片,链接,表示层 css 颜色,大小,位置,行为层 JavaSc ...