Kotlin 扩展函数 #

一、扩展函数概述 #

扩展函数允许在不继承类的情况下,为现有类添加新功能。

二、基本语法 #

2.1 定义扩展函数 #

kotlin
fun String.addExclamation(): String {
    return this + "!"
}

// 使用
val result = "Hello".addExclamation()  // "Hello!"

2.2 this 关键字 #

在扩展函数中,this 指向接收者对象:

kotlin
fun String.printInfo() {
    println("Length: ${this.length}")
    println("Content: $this")
}

"Kotlin".printInfo()
// Length: 6
// Content: Kotlin

2.3 可空接收者 #

kotlin
fun String?.isNullOrBlank(): Boolean {
    return this == null || this.isBlank()
}

val str: String? = null
str.isNullOrBlank()  // true

三、扩展函数示例 #

3.1 字符串扩展 #

kotlin
// 判断是否为数字
fun String.isNumeric(): Boolean {
    return this.all { it.isDigit() }
}

"12345".isNumeric()  // true
"abc".isNumeric()    // false

// 截断字符串
fun String.truncate(maxLength: Int): String {
    return if (length <= maxLength) this else take(maxLength) + "..."
}

"Hello World".truncate(5)  // "Hello..."

// 首字母大写
fun String.capitalizeFirst(): String {
    return if (isEmpty()) this else substring(0, 1).uppercase() + substring(1)
}

"kotlin".capitalizeFirst()  // "Kotlin"

3.2 集合扩展 #

kotlin
// 获取随机元素
fun <T> List<T>.randomElement(): T {
    return this.random()
}

listOf(1, 2, 3, 4, 5).randomElement()

// 分块
fun <T> List<T>.chunked(size: Int): List<List<T>> {
    return this.chunked(size)
}

// 求和(数字列表)
fun List<Int>.sum(): Int {
    return this.reduce { acc, n -> acc + n }
}

3.3 数值扩展 #

kotlin
// 判断是否为偶数
fun Int.isEven(): Boolean = this % 2 == 0

// 判断是否为素数
fun Int.isPrime(): Boolean {
    if (this < 2) return false
    for (i in 2..Math.sqrt(this.toDouble()).toInt()) {
        if (this % i == 0) return false
    }
    return true
}

5.isEven()     // false
7.isPrime()    // true

3.4 日期扩展 #

kotlin
import java.time.LocalDate
import java.time.format.DateTimeFormatter

fun LocalDate.format(pattern: String): String {
    return this.format(DateTimeFormatter.ofPattern(pattern))
}

fun String.toDate(pattern: String): LocalDate {
    return LocalDate.parse(this, DateTimeFormatter.ofPattern(pattern))
}

val date = LocalDate.now()
date.format("yyyy-MM-dd")  // "2024-01-15"

"2024-01-15".toDate("yyyy-MM-dd")

四、扩展属性 #

4.1 定义扩展属性 #

kotlin
val String.halfLength: Int
    get() = length / 2

"Kotlin".halfLength  // 3

4.2 扩展属性示例 #

kotlin
// 判断字符串是否为空或空白
val String?.isNullOrEmpty: Boolean
    get() = this == null || this.isEmpty()

// 判断列表是否只有一个元素
val <T> List<T>.hasSingleElement: Boolean
    get() = size == 1

// 获取文件的扩展名
val String.fileExtension: String
    get() = substringAfterLast(".", "")

4.3 注意事项 #

扩展属性不能有初始化器,必须定义 getter:

kotlin
// 错误
// val String.doubleLength: Int = length * 2

// 正确
val String.doubleLength: Int
    get() = length * 2

五、扩展函数与成员函数 #

5.1 优先级 #

成员函数优先于扩展函数:

kotlin
class Person {
    fun greet() = "Hello from member"
}

fun Person.greet() = "Hello from extension"

val person = Person()
person.greet()  // "Hello from member"

5.2 重载 #

扩展函数可以重载成员函数:

kotlin
class Calculator {
    fun add(a: Int, b: Int) = a + b
}

fun Calculator.add(a: Double, b: Double) = a + b

val calc = Calculator()
calc.add(1, 2)      // 3(成员函数)
calc.add(1.0, 2.0)  // 3.0(扩展函数)

六、扩展函数的作用域 #

6.1 顶层扩展 #

在文件顶层定义,全局可用:

kotlin
// Utils.kt
package com.example.utils

fun String.isEmail(): Boolean {
    return contains("@") && contains(".")
}

6.2 局部扩展 #

在类或函数内部定义:

kotlin
class Processor {
    fun process(text: String) {
        // 局部扩展函数
        fun String.normalize(): String {
            return this.trim().lowercase()
        }
        
        val normalized = text.normalize()
    }
}

6.3 成员扩展 #

在类内部定义扩展:

kotlin
class Service {
    // 成员扩展函数
    fun String.prependPrefix(): String {
        return "PREFIX_$this"
    }
    
    fun process(data: String): String {
        return data.prependPrefix()
    }
}

七、泛型扩展 #

7.1 泛型扩展函数 #

kotlin
fun <T> List<T>.second(): T {
    return this[1]
}

fun <T> T?.ifNull(default: T): T {
    return this ?: default
}

listOf(1, 2, 3).second()  // 2
null.ifNull("default")    // "default"

7.2 类型约束 #

kotlin
fun <T : Number> T.doubleValue(): Double {
    return this.toDouble()
}

fun <T : Comparable<T>> T.isBetween(a: T, b: T): Boolean {
    return this in a..b
}

5.doubleValue()           // 5.0
3.isBetween(1, 5)         // true

八、扩展函数与接收者 #

8.1 带接收者的 Lambda #

kotlin
fun buildString(builder: StringBuilder.() -> Unit): String {
    val sb = StringBuilder()
    sb.builder()
    return sb.toString()
}

val result = buildString {
    append("Hello")
    append(", ")
    append("Kotlin")
}
// "Hello, Kotlin"

8.2 DSL 构建 #

kotlin
class HtmlBuilder {
    private val content = StringBuilder()
    
    fun body(block: HtmlBuilder.() -> Unit) {
        content.append("<body>")
        block()
        content.append("</body>")
    }
    
    fun p(text: String) {
        content.append("<p>$text</p>")
    }
    
    override fun toString() = content.toString()
}

fun html(block: HtmlBuilder.() -> Unit): String {
    return HtmlBuilder().apply(block).toString()
}

val result = html {
    body {
        p("Hello, Kotlin!")
    }
}
// <body><p>Hello, Kotlin!</p></body>

九、标准库扩展函数 #

9.1 标准扩展 #

kotlin
// let
"Kotlin".let { println(it) }

// run
"Kotlin".run { println(length) }

// apply
StringBuilder().apply { append("Hello") }

// also
listOf(1, 2, 3).also { println(it) }

// takeIf
"Kotlin".takeIf { it.length > 3 }

// repeat
3.times { println("Hello") }

9.2 集合扩展 #

kotlin
val list = listOf(1, 2, 3, 4, 5)

list.map { it * 2 }
list.filter { it > 2 }
list.find { it == 3 }
list.any { it > 3 }
list.all { it > 0 }

十、实战示例 #

10.1 验证扩展 #

kotlin
fun String.isValidEmail(): Boolean {
    return matches(Regex("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$"))
}

fun String.isValidPhone(): Boolean {
    return matches(Regex("^\\d{11}$"))
}

fun String.isValidUrl(): Boolean {
    return startsWith("http://") || startsWith("https://")
}

"test@example.com".isValidEmail()  // true
"13800138000".isValidPhone()       // true

10.2 转换扩展 #

kotlin
fun String.toCamelCase(): String {
    return split("_", "-")
        .mapIndexed { index, word ->
            if (index == 0) word.lowercase()
            else word.replaceFirstChar { it.uppercase() }
        }
        .joinToString("")
}

fun String.toSnakeCase(): String {
    return replace(Regex("([a-z])([A-Z])")) { "${it.groupValues[1]}_${it.groupValues[2]}" }
        .lowercase()
}

"hello_world".toCamelCase()   // "helloWorld"
"helloWorld".toSnakeCase()    // "hello_world"

10.3 时间扩展 #

kotlin
import java.time.Duration
import java.time.Instant

fun Instant.formatDuration(): String {
    val duration = Duration.between(this, Instant.now())
    val seconds = duration.seconds
    
    return when {
        seconds < 60 -> "$seconds 秒前"
        seconds < 3600 -> "${seconds / 60} 分钟前"
        seconds < 86400 -> "${seconds / 3600} 小时前"
        else -> "${seconds / 86400} 天前"
    }
}

Instant.now().minusSeconds(300).formatDuration()  // "5 分钟前"

十一、最佳实践 #

11.1 命名规范 #

kotlin
// 推荐:动词开头
fun String.removeSpaces(): String
fun List<Int>.sumAll(): Int

// 布尔返回值用 is/has/can
fun String.isNumeric(): Boolean
fun List<Int>.hasDuplicates(): Boolean

11.2 避免滥用 #

kotlin
// 不推荐:过度使用扩展
fun String.doEverything(): String { }

// 推荐:职责单一
fun String.trimAll(): String
fun String.removeSpecialChars(): String

11.3 使用扩展文件组织 #

kotlin
// StringExtensions.kt
package com.example.extensions

fun String.isEmail(): Boolean { }
fun String.isPhone(): Boolean { }
fun String.truncate(max: Int): String { }

// CollectionExtensions.kt
package com.example.extensions

fun <T> List<T>.second(): T { }
fun <T> List<T>.randomElement(): T { }

十二、总结 #

扩展函数要点:

特性 说明
语法 fun Type.functionName()
this 指向接收者对象
扩展属性 val Type.propertyName
优先级 成员函数优先
作用域 顶层、局部、成员

下一步,让我们学习 内联函数

最后更新:2026-03-27