Kotlin 学习笔记(四)—— 作用域函数、inline 关键字、反引号等 Kotlin 基本用法(上)

简介: Kotlin 学习笔记(四)—— 作用域函数、inline 关键字、反引号等 Kotlin 基本用法(上)

在上一篇中我们见识到了 Kotlin 语言所特有的几种类——数据类、密闭类等,也熟悉了 Kotlin 中集合的常用运算符,以后再也不用担心 Kotlin 集合的相关问题了。这是笔记系列的第四篇,渐入佳境了吧!


1. Kotlin 作用域函数


如果同学们已经在项目中用过 Kotlin 语言,那么一定见过 let 函数!因为每当 Kotlin 检测到某个对象可能为空时,会自动帮我们修改为用 let 函数实现:user.name?.let{ textView.text = it }。这里的 let 函数就是 Kotlin 的作用域函数。除了 let,还有 run、with、apply、also 等等作用域函数。

作用域函数是 Kotlin 内置的,可对数据做一系列操作、变换的函数,与集合操作符类似,作用域函数不仅仅可被集合对象调用,它们还可以被所有对象调用。让我们来看看它们的用法。

let 和 run 函数类似,都会返回函数内闭包的结果,区别在于 let 有闭包参数,而 run 没有闭包参数。使用方法:let{ 闭包 }、run{ 闭包 },有闭包参数意思是 let 在闭包中可以通过 it 拿到它自己本身;而 run 就不行了,只能通过 this 关键字拿到它本身。看 code 1 例子。


// code 1
data class Car(
    val brand: String,
    val price: Int
)
var car: Car? = null
fun funcExample() {
    car = Car("红旗", 199999)
    // let 闭包里可用 it 访问调用者,可返回闭包的执行结果
    val carBrand = car?.let { "car's brand is ${it.brand}" }
    println(carBrand)
    // run 闭包用 this 访问调用者
    val carPrice = car?.run { "car's price is ${this.price}" }
    println(carPrice)
}

also和 apply 函数不会返回闭包里的结果,而上述的 let 和 run 是可以返回闭包结果的。also和 apply 函数的区别也是在于有无闭包参数:also 有闭包参数,apply 没有闭包参数。但是它们都会返回调用者对象,所以它们支持链式调用。

// code 2
// also 闭包里可用 it 访问调用者,后面可链式调用
car?.also {
    println("car 贴牌前 brand = ${it.brand}")
}?.brand = "比亚迪"
// apply 闭包用 this 访问调用者,后面也可链式调用
car?.apply {
    println("car 贴牌后 brand = ${this.brand}")
}?.apply {
    println("car's price = ${this.price}")
}

takeIf 和 takeUnless 这两个作用域函数就用的相对较少了。takeIf 函数里的闭包返回的是 Boolean 类型,如果闭包条件满足,则返回调用者本身,如果不满足,则返回 null。举个栗子来说明吧。

// code 3
car?.takeIf { it.price > 1500000 }
    ?.also { println("车太贵啦!") }    // 闭包为 true,则不为空,执行 also 函数闭包
    ?: run { println("价格还行!") }    // 闭包为 false,则返回空,执行 run 函数闭包

takeUnless 跟 takeIf 是相反的关系,takeUnless 的闭包条件满足则返回空,不满足则返回调用者自己。

repeat 函数。调用方法:repeat( times ) { 闭包 }。将闭包的操作执行 times 次。闭包里面的 it 是当前执行的循环次数,从 0 开始计数。

// code 4
repeat(3) {
        println("car' brand is ${car?.brand}, price is ${car?.price} 当前执行次数为:$it")
}
执行结果:
car' brand is 比亚迪, price is 199999 当前执行索引为:0
car' brand is 比亚迪, price is 199999 当前执行索引为:1
car' brand is 比亚迪, price is 199999 当前执行索引为:2

with 函数。调用方法:with( T ){ 闭包 }。就是将对象 T 去执行闭包里的操作,通常在 Android 开发中,需要对一个 TextView 赋值时,就可以使用 with,比较方便:

// code 5
with(textView) {
    text = "测试"
    textSize = 20F
    setTextColor(ContextCompat.getColor(context, R.color.purple_200))
}


2. Kotlin 自定义操作符


学习 Kotlin 一段时间后,你会发现 Kotlin 给了开发者很大的自我发展空间。比如:支持对类新增扩展函数,支持运算符重载等。所以,我们自己也可以自定义一些操作符,来方便开发。看过 Kotlin 自带的操作符实现的同学们会发现,这些函数都是 inline 关键字修饰的。我们先看下 inline 关键字。

inline 关键字,可以看做是一个是否 内联 的标记。被修饰的函数会在编译时,直接把函数体一起“拷贝”过去,就是将内联函数的代码直接放在内联函数的位置上,这与一般函数不同,在调用一般函数的时候,是指令跳转到被调用函数的入口地址,执行完被调用函数后,指令再跳转回原来跳进来的地方继续执行后面的代码;而由于内联函数是将函数的代码直接放在了函数的位置上,所以没有指令跳转,指令按顺序执行。这样做可以加快代码的运行速度,但是会增加编译时间以及编译后的代码量。

inline 关键字适合修饰不太复杂的但会频繁调用的函数。所以 Kotlin 自带的操作符都是 inline 函数,我们如果要自定义一个操作符,也是需要修饰为 inline 函数。如下就是自定义了一个 convert 操作符,功能类似集合中的 map 函数。

// code 6
inline fun <T, E> Iterable<T>.convert(action: (T) -> E): Iterable<E> {
    val list: MutableList<E> = mutableListOf()
    for (item in this) list.add(action(item))
    return list
}


3. Kotlin 中反引号 ` 的用法


在前面的《Kotlin 学习笔记(一)》 中介绍了下 Kotlin 反引号处理 Kotlin 关键字在 Java 代码里冲突的问题。反引号还有一个作用,就是在 Kotlin 代码中将一个不合法的字符转变为合法字符。举个栗子:

// code 7
object SmallTips {
    // 反引号可将非法字符转换为合法字符
    fun `123`(){
        println("函数名居然为`123`!")
    }
    fun ` `(){
        println("函数名居然为` `!")
    }
    fun `  `(){
        println("函数名居然为`  `!")
    }
}
// 调用也需将反引号加上
SmallTips.`123`()
SmallTips.` `()
SmallTips.`  `()

不可思议吧!函数名本来不能为纯数字或空格符,但是加上反引号就可以了!神奇!那么这有啥用?还记得 Kotlin 的 internal 访问修饰符吗?它限定了被它修饰的函数只能在当前模块使用,而不能在其他模块使用。但是 Java 中是没有这个修饰符的,而 Kotlin 和 Java 又必须完全兼容,所以 Java 也不得不支持这一特性。

那么问题来了,通过反编译查看 Kotlin 中 internal 修饰的函数,在生成的 Java 代码里被编译成了 public 修饰的函数(笑Cry.gif)。为了让 Java 不能访问 Kotlin 中的函数,可以在 Kotlin 中将这些函数的命名改为不合法的形式,然后用反引号包起来,这么做之后,Java 代码是不能调用这些方法的,而 Kotlin 可以调用,从而可以实现在 Java 中屏蔽某些 Kotlin 函数的效果。最后,这种反引号的用法不推荐使用!了解即可!

目录
相关文章
|
22天前
|
安全 Kotlin
Kotlin教程笔记(23) -作用域函数
Kotlin教程笔记(23) -作用域函数
64 6
|
22天前
|
Kotlin
Kotlin教程笔记(21) -高阶函数与函数引用
Kotlin教程笔记(21) -高阶函数与函数引用
30 6
|
1月前
|
Kotlin
Kotlin - 高阶函数与函数引用
Kotlin - 高阶函数与函数引用
29 3
Kotlin - 高阶函数与函数引用
|
1月前
|
IDE 开发工具 Kotlin
Kotlin - 函数与Lambda表达式
Kotlin - 函数与Lambda表达式
42 13
|
26天前
|
IDE 开发工具 Kotlin
Kotlin教程笔记(6) - 函数与Lambda表达式
Kotlin教程笔记(6) - 函数与Lambda表达式
49 1
|
1月前
|
Kotlin
Kotlin教程笔记(21) -高阶函数与函数引用
Kotlin教程笔记(21) -高阶函数与函数引用
24 1
Kotlin教程笔记(21) -高阶函数与函数引用
|
1月前
|
IDE 开发工具 Kotlin
Kotlin - 函数与Lambda表达式
Kotlin - 函数与Lambda表达式
25 1
|
1月前
|
IDE 开发工具 Kotlin
Kotlin - 函数与Lambda表达式
Kotlin - 函数与Lambda表达式
|
1月前
|
安全 Kotlin
Kotlin - 作用域函数
Kotlin - 作用域函数
|
1月前
|
Kotlin
Kotlin教程笔记(21) -高阶函数与函数引用
Kotlin教程笔记(21) -高阶函数与函数引用