前置知识: Kotlin

扩展函数

00:00
3 min Beginner 2026/6/14

扩展函数与扩展属性

概述

扩展函数(Extension Function)是 Kotlin 最具魅力的特性之一。它允许你为已有的类添加新方法,而不需要继承该类或使用装饰器模式。从使用者的角度看,扩展函数就像是被扩展类本身自带的方法一样。

扩展函数的本质是静态方法,它不会修改原始类,也不会影响原始类的行为。编译器只是把扩展函数调用转换为静态方法调用。理解这一点对于正确使用扩展函数至关重要。

基础概念

  • 扩展函数:为已有类添加新方法,语法 fun ClassName.newMethod() { ... }
  • 扩展属性:为已有添加新属性,语法 val ClassName.newProp: Type get() = ...
  • 接收类型:被扩展,如 Stringfun String.xxx()接收类型
  • 接收对象调用扩展函数时,this 指向的对象
  • 静态解析扩展函数编译时确定调用哪个函数,不涉及多态

快速上手

// 为 String 添加扩展函数
fun String.addExclamation(): String = this + "!"

// 为 Int 添加扩展函数
fun Int.isEven(): Boolean = this % 2 == 0

fun main() {
    // 像调用普通方法一样调用扩展函数
    println("Hello".addExclamation())  // Hello!
    println(4.isEven())                 // true
    println(3.isEven())                 // false
}

详细用法

扩展函数基础

// 为 String 添加扩展函数
fun String.wordCount(): Int = this.split(Regex("\\s+")).size

// 为 List 添加扩展函数
fun <T> List<T>.second(): T {
    if (this.size < 2) throw NoSuchElementException("列表没有第二个元素")
    return this[1]
}

// 为可空类型添加扩展函数
fun String?.isNullOrBlank(): Boolean = this == null || this.isBlank()

fun main() {
    println("Hello World Kotlin".wordCount())  // 3
    println(listOf(10, 20, 30).second())       // 20
    println(null.isNullOrBlank())               // true
}

扩展属性

// 为 String 添加扩展属性
val String.firstChar: Char
    get() = this.first()

val String.hasContent: Boolean
    get() = this.isNotBlank()

// 为 Int 添加扩展属性
val Int.isPositive: Boolean
    get() = this > 0

// 注意:扩展属性不能有 backing field,不能初始化
// 错误:val String.lastAccess: Long = System.currentTimeMillis()
// 因为扩展属性不会在对象中存储数据

fun main() {
    println("Hello".firstChar)    // H
    println("Hello".hasContent)   // true
    println(42.isPositive)        // true
}

扩展函数与可空类型

// 为非空类型添加扩展
fun String.trimToLength(maxLength: Int): String {
    return if (this.length <= maxLength) this
    else this.substring(0, maxLength) + "..."
}

// 为可空类型添加扩展
fun String?.safeLength(): Int = this?.length ?: 0

// 更安全的调用方式
fun String?.orElse(default: String): String = this ?: default

fun main() {
    println("Hello World".trimToLength(5))  // Hello...
    println(null.safeLength())               // 0
    println(null.orElse("默认值"))            // 默认值
}

扩展函数中的 this

// 在扩展函数中,this 指向接收者对象
fun String.describe(): String {
    // this 指向调用该方法的 String 对象
    return "字符串 '$this' 的长度是 ${this.length}"
}

// 可以省略 this
fun String.shout(): String = uppercase() + "!!!"

fun main() {
    println("Hello".describe())  // 字符串 'Hello' 的长度是 5
    println("hello".shout())     // HELLO!!!
}

泛型扩展函数

// 为任意类型添加扩展
fun <T> T.printSelf(): T {
    println(this)
    return this
}

// 带约束的泛型扩展
fun <T : Comparable<T>> T.isBetween(min: T, max: T): Boolean {
    return this >= min && this <= max
}

// 为集合添加泛型扩展
fun <T> List<T>.interleave(other: List<T>): List<T> {
    val result = mutableListOf<T>()
    val maxSize = maxOf(this.size, other.size)
    for (i in 0 until maxSize) {
        if (i < this.size) result.add(this[i])
        if (i < other.size) result.add(other[i])
    }
    return result
}

fun main() {
    42.printSelf()                              // 42
    println(5.isBetween(1, 10))                 // true
    println(listOf(1, 2, 3).interleave(listOf("a", "b", "c", "d")))
    // [1, a, 2, b, 3, c, d]
}

扩展函数的解析规则

扩展函数静态解析的,不是多态的:

open class Animal
class Dog : Animal()

// 为 Animal 添加扩展
fun Animal.sound() = "动物叫声"

// 为 Dog 添加扩展
fun Dog.sound() = "汪汪汪"

fun main() {
    val dog: Dog = Dog()
    println(dog.sound())  // 汪汪汪(调用 Dog 的扩展)

    // 关键区别:声明类型决定调用哪个扩展
    val animal: Animal = Dog()
    println(animal.sound())  // 动物叫声(调用 Animal 的扩展,不是 Dog 的)
    // 因为扩展函数是静态解析的,根据变量的声明类型决定
}

扩展函数的作用域

// 顶层扩展函数:在任何地方都可以使用(需要 import)
// File: StringUtils.kt
package com.example.utils

fun String.isEmail(): Boolean = this.contains("@") && this.contains(".")

// 使用时需要 import
// import com.example.utils.isEmail

// 成员扩展函数:只在类内部有效
class Parser {
    // 这个扩展函数只在 Parser 类内部可用
    private fun String.parseToInt(): Int? = this.toIntOrNull()

    fun parse(input: String): Int? {
        return input.parseToInt()  // 在类内部可以使用
    }
}

常见场景

工具函数

// 日期格式化扩展
fun java.time.LocalDateTime.formatChinese(): String {
    return "${this.year}年${this.monthValue}月${this.dayOfMonth}日"
}

// 集合扩展
fun <T> List<T>.randomItem(): T = this.random()

fun <T> List<T>.randomItemOrNull(): T? = if (this.isEmpty()) null else this.random()

// 数值扩展
fun Double.roundTo(decimals: Int): Double {
    var multiplier = 1.0
    repeat(decimals) { multiplier *= 10 }
    return kotlin.math.round(this * multiplier) / multiplier
}

fun main() {
    val now = java.time.LocalDateTime.now()
    println(now.formatChinese())  // 2026年6月14日

    println(3.14159.roundTo(2))  // 3.14
}

防御性编程

// 安全的类型转换
inline fun <reified T> Any.safeCast(): T? = this as? T

// 安全的列表访问
fun <T> List<T>.safeGet(index: Int): T? {
    return if (index in indices) this[index] else null
}

// 非空检查
fun <T : Any> T?.requireNonNull(lazyMessage: () -> String = { "值不能为空" }): T {
    return this ?: throw IllegalArgumentException(lazyMessage())
}

fun main() {
    val value: Any = "Hello"
    val str: String? = value.safeCast()
    println(str)  // Hello

    val list = listOf(1, 2, 3)
    println(list.safeGet(5))  // null(不会越界异常)
}

流式 API

// 链式调用扩展
fun <T> T.applyIf(condition: Boolean, block: T.() -> Unit): T {
    if (condition) block()
    return this
}

fun <T> T.alsoIf(condition: Boolean, block: (T) -> Unit): T {
    if (condition) block(this)
    return this
}

fun main() {
    val result = StringBuilder()
        .applyIf(true) { append("Hello") }
        .applyIf(false) { append(" World") }
        .applyIf(true) { append(" Kotlin") }
        .toString()
    println(result)  // Hello Kotlin
}

注意事项

  • 扩展函数不是真正的方法:它不会修改原始类,只是编译器语法糖
  • 静态解析扩展函数根据变量声明类型决定调用哪个,不是运行时类型
  • 不要滥用扩展:如果一个函数没有紧密关系,用顶层函数更合适
  • 命名冲突:如果扩展函数成员方法同名,成员方法优先
  • 扩展属性不能有状态:没有 backing field,不能存储数据
  • 避免在扩展函数中做耗时操作扩展函数应该轻量,复杂逻辑放在普通函数

进阶用法

中缀扩展函数

// 中缀函数让调用更自然
infix fun String.times(n: Int): String {
    return this.repeat(n)
}

infix fun <T> List<T>.intersect(other: List<T>): List<T> {
    return this.filter { it in other }
}

fun main() {
    println("Ha" times 3)       // HaHaHa
    println("Ha" times 3)       // 等价于 "Ha".times(3)
    println(listOf(1,2,3) intersect listOf(2,3,4))  // [2, 3]
}

扩展函数与运算符重载

// 为 Range 添加扩展
operator fun ClosedRange<Int>.step(step: Int): Iterable<Int> {
    return object : Iterable<Int> {
        override fun iterator(): Iterator<Int> {
            var current = start
            return object : Iterator<Int> {
                override fun hasNext() = if (step > 0) current <= endInclusive else current >= endInclusive
                override fun next(): Int {
                    val result = current
                    current += step
                    return result
                }
            }
        }
    }
}

fun main() {
    for (i in (1..10) step 2) {
        print("$i ")  // 1 3 5 7 9
    }
}

带接收者的函数类型

// 函数类型的接收者
fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()  // 在 StringBuilder 的上下文中执行
    return builder.toString()
}

fun main() {
    val result = buildString {
        // 这里的 this 是 StringBuilder
        append("Hello")
        append(" ")
        append("World")
    }
    println(result)  // Hello World
}

知识检测

学习进度

-- 已学文档
--% 知识覆盖率

学习推荐

专注模式