用更优雅的语法,为现有类添加新功能
一、扩展方法原理
本质 :扩展方法是一种 静态分发 的语法糖,通过 接收者类型(Receiver Type) 为现有类(包括第三方库或系统类)添加新方法,不会侵入原类代码。
编译逻辑:
kotlin
// 定义扩展方法
fun String.addExclamation() = "$this!"
// 编译后等价于:
public static String addExclamation(String $this) {
return $this + "!";
}
关键特性:
- 扩展方法优先级低于类原有方法(同名方法以原类方法为准)
- 扩展方法无法访问私有成员(只能访问 public/protected 成员)
- 支持泛型 、空安全 (如
fun String?.safePrint()
)
二、使用场景
1. 增强第三方库或系统类功能
kotlin
// 为 RecyclerView 添加快速设置 Adapter 的方法
fun RecyclerView.setup(adapter: RecyclerView.Adapter<*>) {
this.adapter = adapter
this.layoutManager = LinearLayoutManager(context)
}
2. 替代 Java 工具类,提升代码可读性
kotlin
// 替代 DateUtils.formatTimestamp(time) → time.formatTimestamp()
fun Long.formatTimestamp(): String = SimpleDateFormat("yyyy-MM-dd").format(Date(this))
3. 链式调用,简化逻辑
kotlin
// 字符串处理链
val result = "hello"
.capitalize() // 原方法
.addExclamation() // 扩展方法
.repeat(2) // 原方法
println(result) // 输出 "Hello!Hello!"
4. 空安全处理
kotlin
// 安全处理可空字符串
fun String?.safeLength(): Int = this?.length ?: 0
val length = nullableString.safeLength()
5. DSL 设计(如布局构建)
kotlin
// 自定义 View 的 DSL
fun Context.myCustomView(init: MyCustomView.() -> Unit): MyCustomView {
return MyCustomView(this).apply(init)
}
三、示例代码
场景 1:为基本类型添加功能
kotlin
// 为 Int 添加是否为偶数的判断
fun Int.isEven(): Boolean = this % 2 == 0
println(4.isEven()) // 输出 true
// 为 List 添加快速交换元素的方法
fun <T> List<T>.swap(index1: Int, index2: Int): List<T> {
val mutableList = this.toMutableList()
mutableList[index1] = mutableList[index2].also { mutableList[index2] = mutableList[index1] }
return mutableList.toList()
}
val list = listOf("A", "B", "C")
println(list.swap(0, 2)) // 输出 [C, B, A]
场景 2:Android 视图扩展
kotlin
// 为 View 添加防抖点击监听
fun View.setOnSingleClickListener(debounceTime: Long = 500, action: (View) -> Unit) {
var lastClickTime = 0L
setOnClickListener { view ->
val currentTime = System.currentTimeMillis()
if (currentTime - lastClickTime > debounceTime) {
action(view)
lastClickTime = currentTime
}
}
}
// 使用
button.setOnSingleClickListener {
showToast("防止重复点击")
}
场景 3:伴生对象扩展
kotlin
class MyClass { companion object }
// 为伴生对象添加方法
fun MyClass.Companion.createFromJson(json: String): MyClass = ...
val instance = MyClass.createFromJson("{...}")
场景 4:扩展属性
kotlin
// 为 String 添加反转属性(注意:扩展属性不能有幕后字段)
val String.reversed: String get() = this.reversed()
println("abc".reversed) // 输出 "cba"
四、注意事项
-
避免滥用:过度扩展会使代码难以维护,优先考虑是否应该通过继承或组合实现
-
作用域控制:
- 使用
import com.example.util.*
导入特定扩展 - 通过
@file:JvmName("StringUtils")
管理扩展文件
- 使用
-
与 Java 互操作:
java// Java 中调用 Kotlin 扩展方法 StringUtilKt.addExclamation("hello");
-
性能影响:扩展方法在编译后转为静态方法,无额外性能损耗
通过扩展方法,让 Kotlin 代码更简洁、更富有表现力! 🚀