2-2-26 快速掌握Kotlin-函数类别

24 阅读5分钟

Kotlin 语言函数类别详解

Kotlin 提供了丰富多样的函数类型,每种类型都有其特定的用途和语法特点。以下是 Kotlin 中主要函数类别的全面解析:

一、按声明位置分类

1. 顶层函数 (Top-Level Functions)

直接定义在文件中,不属于任何类

// 在文件中直接定义
fun greet(name: String): String {
    return "Hello, $name!"
}

// 可直接调用
fun main() {
    println(greet("Alice"))  // 无需类名
}

2. 成员函数 (Member Functions)

定义在类或接口内部

class Calculator {
    // 成员函数
    fun add(a: Int, b: Int): Int {
        return a + b
    }
    
    // 带默认参数的成员函数
    fun multiply(a: Int = 1, b: Int = 1): Int = a * b
}

fun main() {
    val calc = Calculator()
    println(calc.add(5, 3))      // 8
    println(calc.multiply(4, 2)) // 8
}

3. 局部函数 (Local Functions)

在函数内部定义的函数

fun processText(text: String): String {
    // 局部函数,可以访问外部函数的参数和变量
    fun validate(input: String): Boolean {
        return input.isNotBlank() && input.length > 2
    }
    
    fun format(input: String): String {
        return input.trim().uppercase()
    }
    
    return if (validate(text)) format(text) else "INVALID"
}

fun main() {
    println(processText("  hello  "))  // HELLO
    println(processText("a"))          // INVALID
}

二、按行为特性分类

1. 扩展函数 (Extension Functions)

为现有类添加新功能

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

// 为 List<Int> 添加扩展函数
fun List<Int>.averageValue(): Double {
    return if (isEmpty()) 0.0 else sum().toDouble() / size
}

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

fun main() {
    val greeting = "Hello"
    println(greeting.addExclamation())  // Hello!
    
    val numbers = listOf(1, 2, 3, 4, 5)
    println(numbers.averageValue())     // 3.0
    
    val nullableString: String? = null
    println(nullableString.safeLength()) // 0
}

2. 中缀函数 (Infix Functions)

使用中缀表示法调用

infix fun Int.pow(exponent: Int): Int {
    return Math.pow(this.toDouble(), exponent.toDouble()).toInt()
}

infix fun String.repeat(times: Int): String {
    return this.repeat(times)
}

class Person(val name: String) {
    infix fun marry(spouse: Person) {
        println("$name${spouse.name} 结婚了")
    }
}

fun main() {
    println(2 pow 3)  // 8
    println("ha" repeat 3)  // hahaha
    
    val alice = Person("Alice")
    val bob = Person("Bob")
    alice marry bob  // Alice 和 Bob 结婚了
}

3. 内联函数 (Inline Functions)

将函数体直接插入调用处

// 普通高阶函数(会有 lambda 对象创建开销)
fun normalHigherOrder(block: () -> Unit) {
    println("开始执行")
    block()
    println("执行结束")
}

// 内联函数(消除 lambda 开销)
inline fun inlineHigherOrder(block: () -> Unit) {
    println("开始执行")
    block()
    println("执行结束")
}

// 带具体化类型参数的内联函数
inline fun <reified T> checkType(value: Any) {
    if (value is T) {
        println("$value${T::class.simpleName} 类型")
    } else {
        println("$value 不是 ${T::class.simpleName} 类型")
    }
}

fun main() {
    // 编译后,inlineHigherOrder 的代码会被直接插入这里
    inlineHigherOrder {
        println("执行中...")
    }
    
    checkType<String>("Hello")  // Hello 是 String 类型
    checkType<Int>(123)         // 123 是 Int 类型
}

4. 尾递归函数 (Tail Recursive Functions)

使用 tailrec 优化递归调用

// 普通递归(可能导致栈溢出)
fun factorial(n: Int): Int {
    return if (n <= 1) 1 else n * factorial(n - 1)
}

// 尾递归优化版本
tailrec fun factorialTailrec(n: Int, accumulator: Int = 1): Int {
    return if (n <= 1) accumulator else factorialTailrec(n - 1, n * accumulator)
}

// 尾递归查找
tailrec fun findIndex(array: IntArray, target: Int, index: Int = 0): Int {
    return when {
        index >= array.size -> -1
        array[index] == target -> index
        else -> findIndex(array, target, index + 1)
    }
}

fun main() {
    println(factorialTailrec(5))  // 120
    
    val numbers = intArrayOf(1, 3, 5, 7, 9)
    println(findIndex(numbers, 5))  // 2
    println(findIndex(numbers, 2))  // -1
}

5. 操作符重载函数 (Operator Overloading Functions)

重载运算符

data class Vector(val x: Int, val y: Int) {
    // 重载 + 运算符
    operator fun plus(other: Vector): Vector {
        return Vector(x + other.x, y + other.y)
    }
    
    // 重载 - 运算符
    operator fun minus(other: Vector): Vector {
        return Vector(x - other.x, y - other.y)
    }
    
    // 重载 * 运算符
    operator fun times(scalar: Int): Vector {
        return Vector(x * scalar, y * scalar)
    }
    
    // 重载 [] 运算符
    operator fun get(index: Int): Int {
        return when(index) {
            0 -> x
            1 -> y
            else -> throw IndexOutOfBoundsException("Invalid index $index")
        }
    }
    
    // 重载 in 运算符
    operator fun contains(value: Int): Boolean {
        return value == x || value == y
    }
}

fun main() {
    val v1 = Vector(1, 2)
    val v2 = Vector(3, 4)
    
    println(v1 + v2)   // Vector(x=4, y=6)
    println(v2 - v1)   // Vector(x=2, y=2)
    println(v1 * 3)    // Vector(x=3, y=6)
    println(v1[0])     // 1
    println(v1[1])     // 2
    println(3 in v2)   // true
    println(5 in v2)   // false
}

6. 泛型函数 (Generic Functions)

使用类型参数

// 简单的泛型函数
fun <T> printItem(item: T) {
    println("Item: $item")
}

// 多个类型参数
fun <T, R> mapList(list: List<T>, transform: (T) -> R): List<R> {
    return list.map(transform)
}

// 泛型约束
fun <T : Comparable<T>> maxOf(first: T, second: T): T {
    return if (first > second) first else second
}

// 多个约束
fun <T> process(value: T) where T : CharSequence, T : Appendable {
    println("长度: ${value.length}")
    value.append("!")
}

// 泛型扩展函数
fun <T> List<T>.secondOrNull(): T? {
    return if (size >= 2) this[1] else null
}

fun main() {
    printItem(123)           // Item: 123
    printItem("Hello")       // Item: Hello
    
    val numbers = listOf(1, 2, 3)
    val squared = mapList(numbers) { it * it }
    println(squared)         // [1, 4, 9]
    
    println(maxOf(10, 20))   // 20
    println(maxOf("a", "b")) // b
    
    val strings = listOf("a", "b", "c")
    println(strings.secondOrNull())  // b
}

三、按使用方式分类

1. 高阶函数 (Higher-Order Functions)

接收函数作为参数或返回函数

// 接收函数参数
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
    return operation(a, b)
}

// 返回函数
fun getMultiplier(factor: Int): (Int) -> Int {
    return { number -> number * factor }
}

// 使用函数引用
fun isEven(number: Int): Boolean = number % 2 == 0

fun processNumbers(numbers: List<Int>, predicate: (Int) -> Boolean): List<Int> {
    return numbers.filter(predicate)
}

fun main() {
    // 传递 lambda
    val sum = calculate(5, 3) { x, y -> x + y }
    println("Sum: $sum")  // 8
    
    // 传递函数引用
    val numbers = listOf(1, 2, 3, 4, 5)
    val evens = processNumbers(numbers, ::isEven)
    println("偶数: $evens")  // [2, 4]
    
    // 使用返回的函数
    val double = getMultiplier(2)
    println(double(5))  // 10
}

2. Lambda 表达式

匿名函数

fun main() {
    // Lambda 基本形式
    val add: (Int, Int) -> Int = { a, b -> a + b }
    
    // 类型推断
    val multiply = { a: Int, b: Int -> a * b }
    
    // 单参数 lambda 的隐式参数名 it
    val numbers = listOf(1, 2, 3, 4, 5)
    val squares = numbers.map { it * it }
    
    // 带接收者的 lambda
    val builder = StringBuilder().apply {
        append("Hello")
        append(" ")
        append("World")
    }
    
    println(add(3, 4))      // 7
    println(multiply(3, 4)) // 12
    println(squares)        // [1, 4, 9, 16, 25]
    println(builder)        // Hello World
}

3. 匿名函数 (Anonymous Functions)

没有名称的函数表达式

fun main() {
    val numbers = listOf(1, 2, 3, 4, 5)
    
    // 使用 lambda
    val lambdaSum = numbers.reduce { acc, num -> acc + num }
    
    // 使用匿名函数
    val anonymousSum = numbers.reduce(fun(acc: Int, num: Int): Int {
        return acc + num
    })
    
    // 匿名函数的 return 从自身返回
    val firstEven = numbers.find(fun(num: Int): Boolean {
        if (num % 2 == 0) {
            return true  // 只从匿名函数返回
        }
        return false
    })
    
    println("Lambda 求和: $lambdaSum")          // 15
    println("匿名函数求和: $anonymousSum")      // 15
    println("第一个偶数: $firstEven")          // 2
}

4. 函数引用 (Function References)

引用已有函数

fun isPositive(number: Int): Boolean = number > 0
fun square(number: Int): Int = number * number

class MathUtils {
    fun cube(number: Int): Int = number * number * number
}

fun main() {
    val numbers = listOf(-2, -1, 0, 1, 2)
    
    // 顶层函数引用
    val positives = numbers.filter(::isPositive)
    println("正数: $positives")  // [1, 2]
    
    // 成员函数引用
    val utils = MathUtils()
    val cubes = numbers.map(utils::cube)
    println("立方: $cubes")  // [-8, -1, 0, 1, 8]
    
    // 构造函数引用
    data class Person(val name: String, val age: Int)
    
    val createPerson = ::Person
    val person = createPerson("Alice", 25)
    println(person)  // Person(name=Alice, age=25)
    
    // 绑定函数引用
    val alice = Person("Alice", 25)
    val getAge = Person::age
    println("Alice的年龄: ${getAge(alice)}")  // 25
}

四、特殊函数类型

1. 挂起函数 (Suspending Functions)

用于协程

import kotlinx.coroutines.*

// 挂起函数
suspend fun fetchData(): String {
    delay(1000) // 模拟耗时操作
    return "Data loaded"
}

// 挂起函数调用其他挂起函数
suspend fun processData(): String {
    val data = fetchData()
    return data.uppercase()
}

// 带有超时的挂起函数
suspend fun fetchWithTimeout(): String? {
    return withTimeoutOrNull(500) {
        fetchData()
    }
}

fun main() = runBlocking {
    println("开始获取数据...")
    
    // 启动协程执行挂起函数
    val result = fetchData()
    println("结果: $result")
    
    // 并发执行多个挂起函数
    val deferred1 = async { fetchData() }
    val deferred2 = async { fetchData() }
    
    val results = awaitAll(deferred1, deferred2)
    println("并发结果: $results")
}

2. 密封接口/类的函数 (Sealed Class Functions)

配合密封类使用

sealed class Result<out T> {
    // 密封类中的函数
    fun isSuccess(): Boolean = this is Success
    fun isError(): Boolean = this is Error
    
    // 扩展函数模式
    fun getOrNull(): T? = when (this) {
        is Success -> value
        is Error -> null
    }
    
    data class Success<out T>(val value: T) : Result<T>()
    data class Error(val message: String) : Result<Nothing>()
}

fun processResult(result: Result<Int>) {
    when (result) {
        is Result.Success -> println("成功: ${result.value}")
        is Result.Error -> println("错误: ${result.message}")
    }
}

fun main() {
    val success = Result.Success(42)
    val error = Result.Error("出错了")
    
    processResult(success)  // 成功: 42
    processResult(error)    // 错误: 出错了
    
    println(success.getOrNull())  // 42
    println(error.getOrNull())    // null
}

3. DSL 构建器函数 (DSL Builder Functions)

用于创建领域特定语言

class Html {
    private val children = mutableListOf<String>()
    
    fun body(block: Body.() -> Unit) {
        val body = Body().apply(block)
        children.add(body.toString())
    }
    
    override fun toString() = children.joinToString("\n")
}

class Body {
    private val elements = mutableListOf<String>()
    
    fun h1(text: String) {
        elements.add("<h1>$text</h1>")
    }
    
    fun p(text: String) {
        elements.add("<p>$text</p>")
    }
    
    fun div(block: Div.() -> Unit) {
        val div = Div().apply(block)
        elements.add(div.toString())
    }
    
    override fun toString() = elements.joinToString("\n")
}

class Div {
    private var className = ""
    private var content = ""
    
    fun className(name: String) {
        className = " class=\"$name\""
    }
    
    operator fun String.unaryPlus() {
        content = this
    }
    
    override fun toString() = "<div$className>$content</div>"
}

fun html(block: Html.() -> Unit): Html {
    return Html().apply(block)
}

fun main() {
    val page = html {
        body {
            h1("Welcome")
            p("This is a paragraph")
            div {
                className = "container"
                +"Some content"
            }
        }
    }
    
    println(page)
}

五、函数特性组合

1. 扩展函数 + 中缀

infix fun String.repeat(times: Int): String = this.repeat(times)

fun main() {
    println("ha" repeat 3)  // hahaha
}

2. 泛型 + 扩展函数

fun <T> List<T>.secondOrNull(): T? = if (size >= 2) this[1] else null

fun main() {
    val list = listOf("a", "b", "c")
    println(list.secondOrNull())  // b
}

3. 内联 + 泛型

inline fun <reified T> List<*>.filterByType(): List<T> {
    return filterIsInstance<T>()
}

fun main() {
    val mixed = listOf(1, "two", 3, "four", 5)
    val numbers = mixed.filterByType<Int>()
    val strings = mixed.filterByType<String>()
    
    println("数字: $numbers")   // [1, 3, 5]
    println("字符串: $strings") // [two, four]
}

六、函数类型别名

// 为函数类型定义别名
typealias Predicate<T> = (T) -> Boolean
typealias StringMapper = (String) -> String
typealias BinaryOperation = (Int, Int) -> Int

// 使用类型别名
fun filterList(list: List<Int>, predicate: Predicate<Int>): List<Int> {
    return list.filter(predicate)
}

// 高阶函数返回类型别名
fun createValidator(): Predicate<String> {
    return { it.length > 5 }
}

fun main() {
    val numbers = listOf(1, 2, 3, 4, 5)
    val evens = filterList(numbers) { it % 2 == 0 }
    println("偶数: $evens")  // [2, 4]
    
    val validator = createValidator()
    println(validator("short"))   // false
    println(validator("longer"))  // true
}

总结对比表

函数类别关键字/特征主要用途示例
顶层函数工具函数、辅助函数fun calculate() {}
成员函数类内部对象行为、方法class A { fun foo() {} }
扩展函数fun Type.为现有类添加功能fun String.customFun() {}
中缀函数infix提高可读性infix fun Int.add(x: Int)
内联函数inline减少高阶函数开销inline fun<T> process()
尾递归tailrec递归优化tailrec fun factorial()
操作符重载operator自定义运算符行为operator fun plus()
泛型函数<T>类型安全复用fun <T> process(item: T)
高阶函数函数参数/返回值函数式编程fun map(transform: (T)->R)
挂起函数suspend协程异步编程suspend fun fetchData()
密封类函数密封类内部受限类型处理sealed class Result

最佳实践建议

  1. 优先使用顶层函数:对于工具函数,优先考虑定义为顶层函数
  2. 合理使用扩展函数:为系统类添加常用功能时使用
  3. 高阶函数内联化:对于频繁调用的高阶函数,考虑使用 inline
  4. 类型安全优先:充分利用泛型保证类型安全
  5. DSL 模式:构建领域特定语言时使用接收者函数
  6. 函数式组合:通过函数组合实现复杂逻辑
  7. 避免过度嵌套:控制 lambda 嵌套深度,保持可读性
  8. 合理命名:函数名应清晰表达其意图

Kotlin 的函数系统非常强大和灵活,合理利用不同函数类型可以写出更简洁、安全、高效的代码。