Kotlin 扩展方法(Extension Functions)使用详解

用更优雅的语法,为现有类添加新功能

一、扩展方法原理

本质 :扩展方法是一种 静态分发 的语法糖,通过 接收者类型(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"

四、注意事项

  1. 避免滥用:过度扩展会使代码难以维护,优先考虑是否应该通过继承或组合实现

  2. 作用域控制

    • 使用 import com.example.util.* 导入特定扩展
    • 通过 @file:JvmName("StringUtils") 管理扩展文件
  3. 与 Java 互操作

    java 复制代码
    // Java 中调用 Kotlin 扩展方法
    StringUtilKt.addExclamation("hello"); 
  4. 性能影响:扩展方法在编译后转为静态方法,无额外性能损耗

通过扩展方法,让 Kotlin 代码更简洁、更富有表现力! 🚀

更多分享

  1. 一文吃透Kotlin中冷流(Clod Flow)和热流(Hot Flow)
  2. 一文带你吃透Kotlin协程的launch()和async()的区别
  3. Kotlin 委托与扩展函数------新手入门
  4. Kotlin 作用域函数(let、run、with、apply、also)的使用指南
  5. 一文带你吃透Kotlin中 lateinit 和 by lazy 的区别和用法
相关推荐
EQ-雪梨蛋花汤1 小时前
【Part 2安卓原生360°VR播放器开发实战】第四节|安卓VR播放器性能优化与设备适配
android·性能优化·vr
每次的天空1 小时前
Android学习总结之kotlin篇(二)
android·学习·kotlin
刘洋浪子2 小时前
Android Studio中Gradle中Task列表显示不全解决方案
android·ide·android studio
橙子199110162 小时前
Kotlin 中 infix 关键字的原理和使用场景
android·开发语言·kotlin
后端码匠8 小时前
MySQL 8.0安装(压缩包方式)
android·mysql·adb
梓仁沐白9 小时前
Android清单文件
android
董可伦12 小时前
Dinky 安装部署并配置提交 Flink Yarn 任务
android·adb·flink
每次的天空12 小时前
Android学习总结之Glide自定义三级缓存(面试篇)
android·学习·glide
zimoyin12 小时前
Kotlin 协程实战:实现异步值加载委托,对值进行异步懒初始化
java·前端·kotlin
恋猫de小郭13 小时前
如何查看项目是否支持最新 Android 16K Page Size 一文汇总
android·开发语言·javascript·kotlin