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 教程。