kotlin的this和it用法
this用法
this 在 Kotlin 中用于引用当前对象实例,在嵌套类、Lambda、匿名对象等上下文中具有灵活用法。
可以通过 标签化的 this 区分不同作用域的对象。在 高阶函数(如 apply、with)中,this 代表 Lambda 的接收者对象,使代码更加简洁,这些用法让 Kotlin 中的 this 比传统的 Java 更加灵活和强大,特别是在函数式编程和嵌套类的上下文中。
1. 类中的 this
在类的成员方法或属性中,this 用于引用当前对象的实例。
class Person(val name: String) {
fun introduce() {
println("Hello, my name is ${this.name}.")
}
}
fun main() {
val person = Person("Alice")
person.introduce() // 输出: Hello, my name is Alice.
}
这里的 this.name 明确表示访问当前对象的 name 属性。
可选用法: 如果没有歧义,可以省略 this,直接写成 name。
2. 构造函数之间的调用 (this(…))
在主构造函数中可以通过 this(…) 调用类的其他次构造函数。
class Animal(val name: String) {
constructor(name: String, age: Int) : this(name) {
println("Animal's name is $name and age is $age.")
}
}
fun main() {
val dog = Animal("Dog", 5)
}
解释: this(name) 调用了主构造函数。
3. 扩展 this 的作用域
3.1 嵌套类或内部类中的 this
如果类包含嵌套类或内部类,我们可以使用 标签化的 this 来区分不同作用域的对象。
class Outer {
val outerName = "Outer"
inner class Inner {
val innerName = "Inner"
fun printNames() {
println(this.innerName) // 引用内部类的属性
println(this@Outer.outerName) // 引用外部类的属性
}
}
}
fun main() {
val outer = Outer()
val inner = outer.Inner()
inner.printNames()
}
解释:
this.innerName
引用的是内部类的属性。
this@Outer.outerName
明确引用了外部类的属性。
3.2 Lambda 中的 this
在 Lambda 表达式中,this 仍然指向外部类或对象的实例,而不是 Lambda 自己的作用域。
class Car(val name: String) {
fun start() {
println("$name started!")
}
fun drive(action: () -> Unit) {
action() // 调用传入的 Lambda
}
}
fun main() {
val car = Car("Tesla")
car.drive {
this.start() // this 指向的是 Car 实例
}
}
解释: Lambda 表达式中的 this 引用的是 Car 类的当前实例。
4. 带接收者的 Lambda(如 apply 和 with)中的 this
Kotlin 的 apply、with 等高阶函数使用 带接收者的 Lambda,其中 this 代表当前 Lambda 的接收者对象。
4.1 apply 示例
class Person {
var name: String = ""
var age: Int = 0
}
fun main() {
val person = Person().apply {
this.name = "Alice"
this.age = 25
}
println("Name: ${person.name}, Age: ${person.age}")
}
解释: apply 中的 this 指向 Person 对象,因此可以直接访问或修改其属性。
4.2 with 示例
fun main() {
val person = Person()
with(person) {
name = "Bob" // 可以省略 this
age = 30
}
println("Name: ${person.name}, Age: ${person.age}")
}
解释: 在 with 的 Lambda 表达式中,this 默认为 person,可以省略不写。
5. 匿名对象中的 this
在匿名对象中,this 指的是匿名对象本身。
val obj = object {
val id = 1
fun printId() {
println("ID is: ${this.id}")
}
}
fun main() {
obj.printId() // 输出: ID is: 1
}
6. 接口和继承中的 this
在子类中,可以使用 this 调用当前类的属性或方法。要调用父类的属性或方法,可以使用 super。
open class Animal {
open fun sound() {
println("Animal sound")
}
}
class Dog : Animal() {
override fun sound() {
println("Dog barks")
}
fun makeSound() {
this.sound() // 调用 Dog 的 sound 方法
super.sound() // 调用父类的 sound 方法
}
}
fun main() {
val dog = Dog()
dog.makeSound()
}
it 的用法
it 是 Lambda 表达式中单参数的隐式名称。如果 Lambda 只有一个参数且你没有明确指定参数名,Kotlin 会默认用 it 代表该参数。
1. Lambda 单参数的例子
val numbers = listOf(1, 2, 3, 4, 5)
val doubled = numbers.map { it * 2 }
println(doubled) // 输出: [2, 4, 6, 8, 10]
解释:
map 函数中的 Lambda 表达式有一个参数,代表当前元素。
it 指代集合中的每个元素,因此可以通过 it * 2 对其进行操作。
2. 高阶函数中的 it
fun calculate(operation: (Int) -> Int): Int {
return operation(5)
}
fun main() {
val result = calculate { it * it } // 传入 Lambda:5 * 5
println(result) // 输出: 25
}
解释:
it 代表传给 Lambda 的参数(即 5)。
如果不需要自定义参数名,直接使用 it 可以让代码更简洁。
3. 自定义参数时不使用 it
你可以显式定义参数名,那么 it 就不会再使用:
val tripled = numbers.map { number -> number * 3 }
println(tripled) // 输出: [3, 6, 9, 12, 15]
解释: 这里用 number 代替了 it,提升了代码的可读性。
this 和 it 的区别
特性 | this | it |
---|---|---|
作用域 | 引用当前对象或接收者对象。 | 引用 Lambda 表达式中的单个参数。 |
使用场景 | 类、对象、嵌套类、apply 等函数上下文。 | 高阶函数、Lambda 表达式有一个参数时。 |
省略情况 | 如果没有歧义,可以省略。 | 如果 Lambda 表达式中没有指定参数名。 |
标签化用法 | 可以使用标签化的 this@Outer。 | 不能标签化,it 只能用于 Lambda 参数。 |
多参数情况 | 不适用。 | 不能使用,必须显式定义参数名。 |
this 和 it 的用法对比
1. 在 apply 中使用 this
class Person {
var name: String = ""
var age: Int = 0
}
fun main() {
val person = Person().apply {
this.name = "Alice"
this.age = 25
}
println("Name: ${person.name}, Age: ${person.age}")
}
解释: apply 中的 this 是 Person 对象的接收者,可以省略写成 name = “Alice”。
2. 在 let 中使用 it
val name: String? = "Alice"
name?.let {
println("Hello, $it!")
}
解释: 这里的 it 代表 name 的非空值 “Alice”。
3. 选择使用 this 还是 it 的场景
使用 this:当你在类或扩展函数中,操作的是当前对象(接收者)。
使用 it:当你在 Lambda 中有一个参数,并且不想明确命名时。
4. 结合使用 this 和 it
class Box(val label: String) {
fun printLabel() {
listOf("item1", "item2").forEach {
println("$label contains $it")
}
}
}
fun main() {
val box = Box("MyBox")
box.printLabel()
}
解释:
this 引用 Box 类的当前对象,用于访问 label。
it 代表 forEach 中的元素。
5. 总结
this 主要用于引用当前对象或接收者对象,在类、apply 等上下文中频繁使用。
it 主要用于 Lambda 表达式的单个参数,是一种简洁的写法。
在实际开发中,如果需要频繁访问当前对象的成员,this 会更加合适;而在处理简单的 Lambda 表达式时,it 能让代码更加简洁。