Kotlin 扩展函数
最后修改日期:2025 年 3 月 22 日
Kotlin 扩展函数允许你将新的技巧添加到现有的类中,而无需修改它们的蓝图——非常适合改进库或你无法修改的第三方代码。本教程通过生动、真实的例子来阐述扩展函数,使它们的力量栩栩如生。
基本扩展函数
扩展函数通过在其名称前缀目标类型来插入一个类。这里有一个简单的例子,它向 String 添加了一个 welcome 函数,赋予它友好的声音。
fun String.welcome(): String {
return "Welcome, $this, to the team!"
}
fun main() {
val user = "Alice"
println(user.welcome())
}
welcome 用问候语来丰富 String,使用 this 来引用字符串。想象一下在 HR 应用程序中,用热情欢迎新员工——无需修改类。
带参数的扩展函数
扩展函数可以获取参数来展示它们的实力。这个例子向 String 添加了一个 shout 函数,让你根据需要放大文本。
fun String.shout(times: Int): String {
return this.uppercase() + "!".repeat(times)
}
fun main() {
val alert = "warning"
println(alert.shout(3))
}
shout 接受一个 times 参数,用感叹号增强字符串。想象一下在通知系统中,将“警告”变成响亮的警报——可定制且快速。
集合的扩展函数
像 List 这样的集合也可以获得新的能力。这个例子创建了一个 rotate 函数来打乱列表项,保持新鲜感。
fun <T> List<T>.rotate(shift: Int): List<T> {
val size = this.size
if (size == 0) return this
val normalizedShift = (shift % size + size) % size
return this.drop(normalizedShift) + this.take(normalizedShift)
}
fun main() {
val tasks = listOf("Code", "Test", "Deploy")
println(tasks.rotate(1))
}
rotate 移动列表元素,用模运算处理边缘情况。想象一下一个任务调度程序循环优先级——将“代码”旋转到后面可以让你的工作流程保持流畅,而无需更改原始 List。
可空类型的扩展函数
可空类型也受到喜爱,它们带有优雅处理 null 的扩展。这向 String? 添加了一个 safeTrim 函数,无需因空值而绊倒,即可进行整理。
fun String?.safeTrim(): String {
return this?.trim() ?: ""
}
fun main() {
val input: String? = null
println(input.safeTrim())
}
safeTrim 修剪一个可空字符串,如果为 null 则默认为空。非常适合表单处理器清理用户输入——无论是否为 null,它都可以通过 Kotlin 的 Elvis 运算符平滑处理。
自定义类的扩展函数
自定义类也可以萌生新的能力。在这里,Person 类获得了一个 needsID 检查,以标记需要额外检查的未成年人。
class Person(val name: String, val age: Int)
fun Person.needsID(): Boolean {
return this.age < 21
}
fun main() {
val guest = Person("Bob", 19)
println(guest.needsID())
}
needsID 用未成年人检查来标记 Person。想象一下在场地门口,标记 21 岁以下的客人进行身份验证——干净地附加到类上,而无需重写它。
伴生对象的扩展函数
伴生对象可以通过扩展进行升级,增强类似静态的行为。这为 User 的伴生对象添加了一个 fromEmail 工厂。
class User(val username: String) {
companion object
}
fun User.Companion.fromEmail(email: String): User {
return User(email.substringBefore("@"))
}
fun main() {
val user = User.fromEmail("alice@site.com")
println(user.username)
}
fromEmail 从电子邮件中创建一个 User,截取用户名。想想注册流程——从电子邮件中提取一个句柄,而不会使 User 类本身变得混乱。
泛型的扩展函数
泛型也屈服于扩展,在各种类型中提供可重用的技巧。这为 List 添加了一个 summarize 函数,用于快速统计。
fun <T> List<T>.summarize(): String {
return "Count: ${this.size}, Items: ${this.joinToString()}"
}
fun main() {
val scores = listOf(85, 92, 78)
println(scores.summarize())
}
summarize 统计并列出任何 List。想象一个测验应用程序吐出一个分数回顾——通用、简洁,并准备好用于任何数据类型。
带有 Lambda 的扩展
扩展可以使用 lambda 来实现动态行为,让调用者塑造操作。这向 String 添加了一个 transform 函数。
fun String.transform(action: (String) -> String): String {
return action(this)
}
fun main() {
val text = "hello"
println(text.transform { it.capitalize() })
}
transform 将字符串交给一个 lambda,这里将其大写。想想文本编辑器——用户选择调整(大写、反转),扩展就执行,所有这些都不需要触及 String。
链接扩展
扩展可以链接,堆叠效果以实现流畅的工作流程。这在 String 上配对 mask 和 shorten。
fun String.mask(): String = this.replaceRange(1, length - 1, "*".repeat(length - 2))
fun String.shorten(max: Int): String = if (length <= max) this else substring(0, max) + "..."
fun main() {
val email = "alice@site.com"
println(email.mask().shorten(10))
}
mask 隐藏中间字符,然后 shorten 限制长度。非常适合隐私过滤器——在日志中模糊化电子邮件,然后进行截断以供显示,所有这些都在一个流畅的链中完成。
带有接收者作用域的扩展
扩展可以利用接收者的作用域来获得更丰富的逻辑。这向 Any 添加了 logSelf,使用类型信息进行日志记录。
fun Any.logSelf(): String {
return "Log: ${this::class.simpleName} = $this"
}
fun main() {
val num = 42
println(num.logSelf())
}
logSelf 使用 this 及其类名进行日志条目。非常适合调试——任何对象都可以使用类型上下文报告自己,无需子类化。
使用扩展函数的最佳实践
- 保持简洁:为专注于任务的扩展创建精简的扩展,例如
safeTrim,而不是庞大的逻辑炸弹。 - 不要过度使用:谨慎地使用扩展——太多会使你的代码库的清晰度变得模糊。
- 仔细命名:选择像
needsID这样生动的名称,而不是像check这样模糊的名称——意图会闪耀出来。 - 尊重边界:远离私有字段;尊重类的秘密以避免脆弱的黑客攻击。
来源
本教程揭开了 Kotlin 扩展函数的面纱,揭示了它们通过新的操作来美化类的诀窍。通过实际的例子,我们已经看到了它们如何增强模块化和重用,从字符串到自定义类型,都具有 Kotlin 的标志性优雅。
作者
列出 所有 Kotlin 教程。