扩展函数:语法与分派规则
编写扩展函数,并理解静态分派语义。
扩展函数:语法与分派规则 是 CoddyKit 上的免费 Kotlin Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Kotlin Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Kotlin Academy 课程共包含 4 节课。
什么是扩展函数
扩展函数可以在不修改现有类或使用继承的情况下,向现有类添加新函数。
扩展函数的基本语法
在函数名称前加上要扩展的类型,这个类型称为“接收者类型”。
fun String.shout(): String = uppercase() + "!"
println("hello".shout()) // HELLO!
fun Int.isEven() = this % 2 == 0
println(4.isEven()) // true扩展函数中的接收者对象
在扩展函数内部,接收者对象指代当前接收者。
fun List<Int>.secondOrNull(): Int? {
return if (size >= 2) this[1] else null
}
println(listOf(10, 20, 30).secondOrNull()) // 20
println(listOf(5).secondOrNull()) // null静态分派:扩展函数不会重写
扩展函数会在编译时根据声明类型进行静态解析——它们不是 NOT 虚函数。
open class Base
class Child : Base()
fun Base.greet() = "Hello from Base"
fun Child.greet() = "Hello from Child"
val obj: Base = Child()
println(obj.greet()) // "Hello from Base" (static dispatch!)扩展函数与成员函数
如果某个类具有与扩展函数签名相同的成员函数,则始终优先调用成员函数。
class Greeter {
fun hello() = "member hello"
}
fun Greeter.hello() = "extension hello" // shadowed!
println(Greeter().hello()) // "member hello"可空接收者扩展
您可以扩展可空类型。在函数内部,请通过检查接收者是否为空来处理空值。
fun String?.orEmpty() = this ?: ""
fun Any?.toStringSafe() = this?.toString() ?: "null"
println(null.orEmpty()) // ""
println(42.toStringSafe()) // "42"可见性与作用域
扩展可以位于顶层(全局范围)、类中(成员扩展)或文件中。它们遵循常规的可见性规则。
// Top-level extension:
fun List<String>.joinUppercase() = joinToString { it.uppercase() }
// Private to file:
private fun String.clean() = trim().lowercase()伴生对象扩展
向伴生对象添加扩展,以扩展类级别的命名空间。
class User(val name: String) {
companion object
}
fun User.Companion.guest() = User("Guest")
val guest = User.guest()标准库类型上的扩展
您可以扩展任何类型,包括内置类型。
fun Double.roundTo(decimals: Int): Double {
val factor = Math.pow(10.0, decimals.toDouble())
return Math.round(this * factor) / factor
}
println(3.14159.roundTo(2)) // 3.14组织扩展
请将某个类型的扩展集中到专用文件中,例如 StringExtensions.kt、DateExtensions.kt。
// StringExtensions.kt
fun String.titleCase() = split(" ")
.joinToString(" ") {
it.replaceFirstChar { c -> c.uppercase() }
}
println("hello world".titleCase()) // Hello World扩展无法访问私有成员
扩展只能访问公共成员和内部成员,无法访问私有成员或受保护成员。
class Secret {
private val key = "hidden"
val name = "public"
}
fun Secret.reveal() {
println(name) // OK
// println(key) // Error: key is private
}快速检查
如果类成员函数和扩展函数具有相同的签名,会调用哪一个?
回顾
扩展函数可以在不修改类的情况下向任何类添加行为。它们采用静态分派(不会重写)。成员函数优先于扩展函数。请使用可空接收者来编写空值安全的辅助函数。下一步:扩展属性!
常见问题解答
「扩展函数:语法与分派规则」课时是免费的吗?
是的 — 「扩展函数:语法与分派规则」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Kotlin Academy 课程的其余内容,请升级到 CoddyKit PRO。 Kotlin Academy 课程共包含 4 节课。
「扩展函数:语法与分派规则」这节课中我会学到什么?
编写扩展函数,并理解静态分派语义。 你通过在浏览器中直接运行的动手代码来练习 Kotlin Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Kotlin Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Kotlin Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「扩展函数:语法与分派规则」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Kotlin Academy 课中编写并运行代码吗?
能。每节 Kotlin Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。