介绍
本篇介绍Kotlin中的解构声明,实现同时多变量声明。以及在Kotlin中This表达式的实现效果。
解构声明
示例:
val (name,age,sex)=person
在上面的示例中,我们把一个对象解构成了很多个变量。这种语法叫做:解构声明。
一个解构声明可以同时创建多个变量,在上面的示例中,就创建了三个新的变量:name,age,sex。然后我们可以在代码中直接使用:
示例:
val (name,age,sex)=person
println(name)
println(age)
println(sex)
为什么会这样?Kotlin
是怎么将person
对象的属性对应到具体的name,age,sex
中的呢?
那是因为一个解构声明之后,在实际编译的代码中:
val name = person.component1()
val age = person.component2()
val sex = person.component3()
任何表达式都可以出现在解构声明的右侧,只要可以对它调用所需数量的component
函数即可。
但是我们自定义的时候componentN()
,需要operator
关键字标记,才能允许在解构声明中使用。
for循环中的解构声明
我们除了在定义变量的时候可以使用解构声明,我们在For等循环操作中也可以使用解构声明。
示例:
for((a,b) in collection){
...
}
在示例中的变量a,b 的值会自动取对应集合中的元素的component1
和component2
函数获取的返回值。
常用示例
介绍和学习几种解构声明的常用。(我们了解有这方面的知识后,实际代码编写过程中。可以一点点尝试使用。这样你的代码将更高效)。
1.从函数中返回两个变量:例如我们需要该函数返回两个数据一个结果,一个状态。我们可以简洁实现该需求。
示例:
data class Result(val result: Int, val status: Status)
fun function(……): Result {
// 各种计算
return Result(result, status)
}
// 现在,使用该函数:
val (result, status) = function(……)
因为数据类型自动声明component
函数。所以我们可以直接使用解构声明快速实现需求。
2.快速获取映射数据:例如我们获取map的数据时通常需要得到Key和value。那么我们希望直接使用解构声明获取数据时:可以很快捷的实现效果。
示例:
for ((key, value) in map) {
// 使用该 key、value 做些事情
}
在Kotlin标准库中,针对集合等,提供类相关的扩展。
所以我们才可以在for循环中自由的使用解构声明。
过滤未使用的变量
我们如果通过解构声明只需要获取某个值,另外的值不想获取。例如我们要取第二个值,不想取第一个值,那么我们可以通过下划线来声明替代。
示例:
val (_,age,sex)=person
在上面的示例代码中,编译运行的时候,就会自动跳过component1()
函数的调用。达到不获取该变量值的需求。
Lambda 表达式中使用
如果 lambda 表达式具有 Pair
类型(或者 Map.Entry
或任何其他具有相应 componentN
函数的类型)的参数,那么可以通过将它们放在括号中来引入多个新参数来取代单个新参数:
map.mapValues { entry -> "${entry.value}!" }
map.mapValues { (key, value) -> "$value!" }
注意声明两个参数和声明一个解构对来取代单个参数之间的区别:
{ a //-> …… } // 一个参数
{ a, b //-> …… } // 两个参数
{ (a, b) //-> …… } // 一个解构对
{ (a, b), c //-> …… } // 一个解构对以及其他参数
如果解构的参数中的一个组件未使用,那么可以将其替换为下划线,以避免编造其名称:
map.mapValues { (_, value) -> "$value!" }
你可以指定整个解构的参数的类型或者分别指定特定组件的类型:
map.mapValues { (_, value): Map.Entry<Int, String> -> "$value!" }
map.mapValues { (_, value: String) -> "$value!" }
This 表达式
我们在代码中,为了表示当前的对象通常使用this关键字替代。
特别是java中This使用的很多。kotlin中也有this表达式。
- 在类的成员中,this指的是该类的当前对象。
- 在扩展函数或带有接收者的函数字面值中,thsi表示在点左侧传递的接收者参数。(
.
)
限定符
如果this没有限定符的时候,它值的是最内层的包含它的作用域。而要访问来自外部作用域的this。通常要加上限定符。
示例:
class A { // 隐式标签 @A
inner class B { // 隐式标签 @B
fun Int.foo() { // 隐式标签 @foo
val a = this@A // A 的 this
val b = this@B // B 的 this
val c = this // foo() 的接收者,一个 Int
val c1 = this@foo // foo() 的接收者,一个 Int
val funLit = lambda@ fun String.() {
val d = this // funLit 的接收者
}
val funLit2 = { s: String ->
// foo() 的接收者,因为它包含的 lambda 表达式
// 没有任何接收者
val d1 = this
}
}
}
}
通过@Lable
来实现。
implicit this
当对This 调用成员函数时,可以省略掉this部分。但是如果有一个同名的非成员函数,那么我们要谨慎使用,建议添加上this。否则可能会出现调用同名的非成员。
fun printLine() { println("Top-level function") }
class A {
fun printLine() { println("Member function") }
fun invokePrintLine(omitThis: Boolean = false) {
if (omitThis) printLine()
else this.printLine()
}
}
A().invokePrintLine() // Member function
A().invokePrintLine(omitThis = true) // Top-level function
到这里,我们也就简单的接触类解构声明和this表达式。
我们明白之后,需要在实际代码过程中去不断使用才能加深我们的理解和掌握。
评论区