kotlin Standard中的内联函数示例详解

let、with、run、apply、also、takeIf、takeUnless、repeat函数的使用

kotlin Standard.kt文件中,提供了一些内联函数,这些内联函数可以减少代码量,在使代码优美的同时,打打提高开发效率。它们分别为:

run、with、let、also、apply

let

let函数的定义如下:

public inline fun <T, R> T.let(block: (T) -> R): R = block(this)

默认当前这个对象作为闭包的it参数,函数接受一个lambda函数块返回值是函数里面最后一行,或者指定return
let函数的一般结构为:

obj.let {
 it.todo//it指代obj对象实例
 ...
}
//在需要判断obj是否为null时
obj?.let {
 it.todo//it指代obj对象实例
 ...
}

使用实例:初始化user

 val user = User()
 val result= user.let {
   it.account = "12306"
   it.address = "粤海街道"
   it.address
}
println(result)
//运行结果
>>粤海街道

适用场景:

  • 用let函数处理需要针对一个可null的对象统一做判空处理
  • 明确一个变量所在特定作用域的范围

with

with函数的定义如下:

public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()

with函数不是以扩展函数的形式存在,它是将对象作为参数,在函数块内通过this指代该对象。with函数是接收了两个参数,分别为对象receiver和一个lambda函数块,返回值为函数块的最后一行或指定return表达式。
with的一般结构为:

with(obj){
  this.todo
  todo//this可省略
  ...
}

使用实例:将地址影射到UI上

with(user){
 tView.text = address
}

适用范围:

适用于调用一个类的多个方法,可以省去对象名直接调用方法(例如将数据影射到ui上时)

run

run函数的定义如下:

public inline fun <T, R> T.run(block: T.() -> R): R = block()

run函数接受一个lambda函数块,以闭包的形式返回函数块的最后一行或指定return表达式。观察函数的定义可以发现,run函数为一个扩展函数,而其接受的参数和with函数第二个参数相同,run函数可以理解为let函数和with函数的结合体。
run函数的一般结构为:

obj.run {
  this.todo
  todo//this可省略
  ...
}

使用实例:将地址影射到UI上

user.run {
 tView.text = address
}

适用范围:

适用于let和run函数的场景,run函数相较于let函数省去了必须适用it指代参数的麻烦,相较于with函数弥补了对象判空的问题

also

also函数的定义如下:

public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this }

also函数的定义和let函数的类似,只是also函数返回的为传入对象的本身。

also函数的一般结构和使用方法和let函数类似:

obj.also {
  it.todo//it指代obj对象实例
  ...
}
//在需要判断obj是否为null时
obj?.let {
  it.todo//it指代obj对象实例
  ...
}

适用范围:

also函数返回值微传入方法的对象本身,所以可用来进行函数的链式调用

apply

apply函数的定义如下:

public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }

apply函数的定义和run函数的类似,唯一的区别就是apply函数返回的为传入对象的本身。

apply函数一般结构如下:

apply函数一般结构如下:
obj.apply {
  this.todo
  todo//this可省略
  ...
}

使用实例:给对象赋值

var user = User().apply {
      account = "12306"
    }

适用场景:

apply函数和run函数除了返回值外,整体功能和作用类似,一般用于对象初始化时对属性进行赋值。

总结:

这里我们总结对比一下这五个函数,这五个函数的特性非常简单,区别也无非是接受的参数和返回的类型不同。其中,对于with,run,apply接收者是this(可以省略),而let和also则使用it接受且不可s省略对于;

对于with,run,let返回值是返回值是函数里面最后一行,或者指定return,而apply和also返回值是调用者本身。

函数名 接受者 返回值
let it 最后一行
with this 最后一行
run this 最后一行
also it 调用者本身
apply this 调用者本身

如何选择可以参考下图

takeIf、takeUnless、repeat

takeIf & takeUnless

takeIf函数的定义如下:

public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? = if (predicate(this)) this else null

可以看出:takeIf函数接受一个入参类型为调用者的类型T,返回值为Boolean类型的lambda函数块。takeIf函数根据lambda函数返回值返回的数据,为true返回调用者本身,否则返回null

takeUnless函数的定义如下:

public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? = if (!predicate(this)) this else null

不难看出,takeUnless相对比takeIf只是在返回值调用predicate(this)进行了取反操作,takeUnless的作用效果和takeIf正好相反!

takeIf函数一般结构如下:

obj.takeIf{
  ...
  true/fals
}

使用实例:

//根据age为user赋值,若age在1-100之间,为user.age赋值age,否则user.age为null
var age
...
user.age = age.takeIf {
  age in 1..99
}.toString()

user.age = age.ta {
  age in 100..0
}.toString()

repeat

repeat函数的定义如下:

public inline fun repeat(times: Int, action: (Int) -> Unit) { for (index in 0 until times) { action(index) } }

函数接受一个int类型数据times,和一个入参为int类型,无返回值的lambda函数action,并通过for循环重复的调用times次action函数

函数的一般结构如下:

repeat(int){
  todo
}

使用实例:

//快速的为list添加十条数据
var list = ArrayList<User>()
repeat(10){
  list.add(User())
}

适用场景:该函数可以用来避免写循环语句,可以用来遍历数据。

结语:

Kotlin Standard.kt中的标准库函数已基本讲解完毕,其中涉及到了高阶函数和lambda函数,相关知识可通过官方文档学习,同时建议读者将每个函数都实际敲一遍,并通过查看他们编译后的class文件加深对函数的理解。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

(0)

相关推荐

  • Kotlin 内联函数详解及实例

    Kotlin 内联函数详解及实例 概述 在说内联函数之前,先说说函数的调用过程. 调用某个函数实际上将程序执行顺序转移到该函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方.这种转移操作要求在转去前要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保存地址继续执行.也就是通常说的压栈和出栈.因此,函数调用要有一定的时间和空间方面的开销.那么对于那些函数体代码不是很大,又频繁调用的函数来说,这个时间和空间的消耗会很大. 那怎么解决这个性能消耗问题呢,这个时候

  • Kotlin中关于内联函数的一些理解分享

    前言 看了很多博客,才明白了内联的含义,其实最根本的就是将写在别处的代码拷贝到你现在执行的方法中,相当于在一个方法中执行,java的方法执行是需要压栈出栈的对吧,如果是两三个方法那就是两三次的压栈出栈,为了节省这个操作,提高一定的效率,kotlin就出了这么个函数.但又想想,如果是个超级大的函数,考来考去的也是很麻烦啊,所以这东西需要自己权衡吧,遵守单一职责,降低代码圈发杂度才是根本. 内联函数的理解 inline函数(内联函数)从概念上讲是编译器使用函数实现的真实代码来替换每一次的函数调用,带

  • kotlin Standard中的内联函数示例详解

    let.with.run.apply.also.takeIf.takeUnless.repeat函数的使用 kotlin Standard.kt文件中,提供了一些内联函数,这些内联函数可以减少代码量,在使代码优美的同时,打打提高开发效率.它们分别为: run.with.let.also.apply let let函数的定义如下: public inline fun <T, R> T.let(block: (T) -> R): R = block(this) 默认当前这个对象作为闭包的it

  • C++类中的特殊成员函数示例详解

    前言 C++类中有几个特殊的非静态成员函数,当用户未定义这些函数时,编译器将给出默认实现.C++11前有四个特殊函数,C++11引入移动语义特性,增加了两个参数为右值的特殊函数.这六个函数分别是: 1.默认构造函数 默认构造函数指不需要参数就能初始化的构造函数.包含无参和所有参数有默认值两种类型的构造函数. 2.复制构造函数 复制构造函数指使用该类的对象作为参数的构造函数.可以有其他参数,但必须提供默认值. 3.复制赋值运算符 重载等号=,将该类的对象赋值给已定义对象. 4.析构函数 没啥可说的

  • numpy中hstack vstack stack concatenate函数示例详解

    目录 大纲 1.concatenate() 2.stack() 3.vstack() 4.hstack() 5.tf中的stack() 大纲 本文主要介绍一下numpy中的几个常用函数,包括hstack().vstack().stack().concatenate(). 1.concatenate() 我们先来介绍最全能的concatenate()函数,后面的几个函数其实都可以用concatenate()函数来进行等价操作. concatenate()函数根据指定的维度,对一个元组.列表中的li

  • Kotlin协程的基础与使用示例详解

    目录 一.协程概述 1.概念 2.特点 3.原理 1)续体传递 2)状态机 二.协程基础 1.协程的上下文 2.协程的作用域 3.协程调度器 4.协程的启动模式 5.协程的生命周期 1)协程状态的转换 2)状态标识的变化 三.协程使用 1.协程的启动 1)runBlocking方法 2)launch方法 3)async方法 4)suspend关键字 5)withContext方法 6)suspend方法 2.协程间通信 1)Channel 2)Channel的容量 3)produce方法与act

  • Go语言中的字符串处理方法示例详解

    1 概述 字符串,string,一串固定长度的字符连接起来的字符集合.Go语言的字符串是使用UTF-8编码的.UTF-8是Unicode的实现方式之一. Go语言原生支持字符串.使用双引号("")或反引号(``)定义. 双引号:"", 用于单行字符串. 反引号:``,用于定义多行字符串,内部会原样解析. 示例: // 单行 "心有猛虎,细嗅蔷薇" // 多行 ` 大风歌 大风起兮云飞扬. 威加海内兮归故乡. 安得猛士兮守四方! ` 字符串支持转义

  • Python模块glob函数示例详解教程

    目录 本文大纲 支持4个常用的通配符 1)glob()函数 2)iglob()函数 3)escape()函数 总结 本文大纲 glob模块也是Python标准库中一个重要的模块,主要用来查找符合特定规则的目录和文件,并将搜索的到的结果返回到一个列表中.使用这个模块最主要的原因就是,该模块支持几个特殊的正则通配符,用起来贼方便,这个将会在下方为大家进行详细讲解. 支持4个常用的通配符 使用glob模块能够快速查找我们想要的目录和文件,就是由于它支持*.**.? .[ ]这三个通配符,那么它们到底是

  • 详解Python中生成随机数据的示例详解

    目录 随机性有多随机 加密安全性 PRNG random 模块 数组 numpy.random 相关数据的生成 random模块与NumPy对照表 CSPRNG 尽可能随机 os.urandom() secrets 最佳保存方式 UUID 工程随机性的比较 在日常工作编程中存在着各种随机事件,同样在编程中生成随机数字的时候也是一样,随机有多随机呢?在涉及信息安全的情况下,它是最重要的问题之一.每当在 Python 中生成随机数据.字符串或数字时,最好至少大致了解这些数据是如何生成的. 用于在 P

  • RxJS中的Observable和Observer示例详解

    目录 引言 概念 牛刀小试 Observable Observable 剖析 Observer 结束语 引言 最近在项目当中别的小伙伴使用到了Rxjs,我一眼看上去有点懵,感觉挺复杂,挺绕的.于是抓紧补补课,然后就可以和小伙伴们一起交流怎么能优雅的使用Rxjs.由于内容比较多,会分为三篇来讲解说明 初识 RxJS中的 Observable 和 Observer 细说 RxJS中的 Operators 在谈 RxJS中的 Subject和Schedulers 概念 RxJS是一个库,可以使用可观察

  • Python PyQt5中窗口数据传递的示例详解

    目录 单一窗口数据传递 多窗口数据传递:调用属性 多窗口数据传递:信号与槽 开发应用程序时,若只有一个窗口则只需关心这个窗口里面的各控件之间如何传递数据.如果程序有多个窗口,就要关心不同的窗口之间是如何传递数据. 单一窗口数据传递 对于单一窗口的程序来说,一个控件的变化会影响另一个控件的变化通过信号与槽的机制就可简单解决. import sys from PyQt5.QtWidgets import QWidget, QLCDNumber, QSlider, QVBoxLayout, QAppl

  • python中强大的format函数实例详解

    python中format函数用于字符串的格式化 自python2.6开始,新增了一种格式化字符串的函数str.format(),此函数可以快速处理各种字符串. 语法 它通过{}和:来代替%. 请看下面的示例,基本上总结了format函数在python的中所有用法 #通过位置 print '{0},{1}'.format('chuhao',20) print '{},{}'.format('chuhao',20) print '{1},{0},{1}'.format('chuhao',20) #

随机推荐