1. 概述

在 Kotlin 中,this 关键字用于引用当前正在执行方法的类实例。除此之外,this 还有多种高级用法,在不同上下文中能发挥重要作用。

对于有经验的开发者来说,this 并不陌生,但在 Kotlin 中它的语义更丰富,尤其结合扩展函数、内部类和构造器委托时,容易踩坑 ❗。本文将系统梳理 this 的各种使用场景,帮你彻底掌握其行为逻辑。

2. 使用 this 访问类成员

在类的方法中,可以通过 this 显式访问属性或调用成员函数:

class Counter {
    var count = 0

    fun incrementCount() {
        this.count += 2
    }
}

典型用途:消除命名冲突

当局部变量与类属性同名时,必须使用 this 区分:

fun setCount(count: Int) {
    this.count = count // this.count 是属性,count 是参数
}

虽然大多数情况下可以省略 this(编译器自动推断),但显式写出能提升代码可读性,特别是在复杂方法中。

3. 将类实例作为对象传递

this 可以代表当前对象实例本身,常用于将自身传给外部函数:

class Foo {
    var count = 0

    fun incrementCount() {
        incrementFoo(this)
    }
}

private fun incrementFoo(foo: Foo) {
    foo.count += 2
}

fun main() {
    val foo = Foo()
    foo.incrementCount()
    println("Final count = ${foo.count}") // 输出: Final count = 2
}

⚠️ 注意:这种模式常见于事件回调、注册机制或依赖注入场景中。通过传递 this,外部函数可以获得对该实例的引用并操作其状态。

你也可以将 this 赋值给局部变量,例如缓存当前实例:

val instance = this

4. 二级构造器中的构造委托

在 Kotlin 中,所有二级构造器必须通过 this 关键字委托到主构造器或其他二级构造器:

class Car(val id: String, val type: String) {
    constructor(id: String): this(id, "unknown")
}

✅ 规则要点:

  • 所有 constructor 必须最终链式调用到主构造器
  • 委托使用 this(...) 语法完成
  • 可定义多个二级构造器,适用于不同参数组合

❌ 错误示例(无法编译):

class Car(val id: String, val type: String) {
    constructor(id: String) { // 缺少委托,报错
        // ...
    }
}

📌 提示:如果你发现需要大量二级构造器,考虑改用默认参数的主构造器,这是更 Kotlin 风格的做法:

class Car(val id: String, val type: String = "unknown")

5. 使用限定符访问外部实例(Qualified this)

在嵌套类、扩展函数或带接收者的 Lambda 中,this 的指向可能产生歧义。此时可通过 qualified this 明确指定作用域。

内部类访问外部实例

class Outside {
    inner class Inside {
        fun innerInstance() = this           // 当前 Inner 实例
        fun outerInstance() = this@Outside   // 外部类 Outside 实例
    }
}

✅ 使用场景举例:

class Activity {
    private var clickCount = 0

    inner class ClickHandler {
        fun onClick() {
            this@Activity.clickCount++ // 修改外层 activity 的状态
        }
    }
}

在扩展函数中访问外部 this

fun String.processWith(list: List<String>) {
    list.forEach {
        println("$this: $it") // this 指向被扩展的 String
    }
}

fun main() {
    "prefix".processWith(listOf("a", "b"))
    // 输出:
    // prefix: a
    // prefix: b
}

更复杂的例子:多层 receiver 的 Lambda

class OuterScope {
    fun StringBuilder.addWithContext(block: StringBuilder.() -> Unit) {
        block() // block 内部的 this 是 StringBuilder
    }

    fun example() {
        buildString {
            addWithContext {
                append(this@OuterScope.toString()) // 引用 OuterScope 实例
            }
        }
    }
}

📌 小技巧:IDE 通常会高亮不同的 this,鼠标悬停可查看其确切作用域。

6. 总结

this 在 Kotlin 中不仅是简单的“当前实例”引用,更是处理作用域、消除歧义和实现构造委托的核心工具 ✅。

关键点回顾:

场景 用法
成员访问 this.property 解决命名冲突
对象传递 this 传给函数或赋值变量
构造委托 二级构造器用 this(...) 委托主构造器
限定访问 this@Label 获取外层实例

熟练掌握这些模式,能让你写出更清晰、意图更明确的 Kotlin 代码,避免因作用域混乱导致的逻辑 bug。

完整示例代码见 GitHub 仓库


原始标题:Introduction to “this” Keyword in Kotlin