1. 概述

Kotlin 语言的一大优势在于其表达力强的语法设计,其中将函数作为参数使用,并结合默认参数值的能力,是提升代码可读性和灵活性的重要特性。

本文将围绕 Kotlin 中的默认参数、函数作为参数、以及如何将函数作为带有默认值的参数来使用展开讨论,并通过示例代码帮助你掌握这些技巧。

2. 默认参数

Kotlin 支持为函数参数设置默认值,这大大减少了函数重载的需要。

来看一个简单的例子:

fun greeting(name: String = "Baeldung"): String {
    return "Hi $name"
}

上面的 greeting() 函数中,name 参数有一个默认值 "Baeldung"。如果我们调用这个函数时不传 name,它会自动使用默认值:

assertEquals("Hi Baeldung", greeting())

当然也可以传入自定义值:

assertEquals("Hi Kai", greeting("Kai"))

优点:通过默认参数,我们避免了写多个重载函数,使代码更简洁清晰。

3. 函数作为参数

在 Kotlin 中,函数是一等公民(first-class),这意味着你可以将函数赋值给变量,也可以将函数作为参数传递给其他函数。

我们来扩展一下前面的 greeting() 函数,添加一个函数类型的参数:

fun greeting1(name: String = "Baeldung", buildMessage: (String) -> String): String {
    return "Hi $name, ${buildMessage(name)}"
}

这里,buildMessage 是一个函数参数,它接收一个 String 类型的输入,并返回一个 String 类型的结果。

我们可以用 Lambda 表达式定义一个满足这个签名的函数:

val msgByCharCount: (String) -> String = { input: String ->
    "your name has an ${if (input.length % 2 == 1) "odd" else "even"} number of letters."
}

这个函数根据名字长度的奇偶性生成不同的消息。接着我们就可以把它作为参数传给 greeting1()

val msgWithDefaultName = greeting1(buildMessage = msgByCharCount)
assertEquals("Hi Baeldung, your name has an even number of letters.", msgWithDefaultName)

val kaiMsg = greeting1(name = "Kai", buildMessage = msgByCharCount)
assertEquals("Hi Kai, your name has an odd number of letters.", kaiMsg)

4. 带默认值的函数参数

Kotlin 允许我们为函数类型的参数也设置默认值。这意味着,如果调用者没有提供对应的函数参数,就使用默认实现

我们来看一个带默认函数参数的版本:

fun greeting2(name: String = "Baeldung", buildMessage: (String) -> String = { input: String ->
    "your name is ${if (input.length > 3) "long" else "short"}."
}): String {
    return "Hi $name, ${buildMessage(name)}"
}

此时调用 greeting2() 时,可以不传 buildMessage,使用默认实现:

val result1 = greeting2()
assertEquals("Hi Baeldung, your name is long.", result1)

val result2 = greeting2("Kai")
assertEquals("Hi Kai, your name is short.", result2)

当然,也可以传入自定义的函数逻辑:

val result3 = greeting2(buildMessage = msgByCharCount)
assertEquals("Hi Baeldung, your name has an even number of letters.", result3)

val result4 = greeting2(name = "Kai", buildMessage = msgByCharCount)
assertEquals("Hi Kai, your name has an odd number of letters.", result4)

4.1 忽略函数参数的默认实现

有时候我们希望默认函数忽略传入的参数,直接返回固定值。此时可以在 Lambda 中使用下划线 _ 来忽略参数:

fun greeting3(name: String = "Baeldung", buildMessage: (String) -> String = { _ -> "how do you do?" }): String {
    return "Hi $name, ${buildMessage(name)}"
}

此时无论传入什么名字,buildMessage 都会返回固定值:

val result1 = greeting3()
assertEquals("Hi Baeldung, how do you do?", result1)

val result2 = greeting3("Kai")
assertEquals("Hi Kai, how do you do?", result2)

小技巧:使用 _ 来忽略不使用的参数,既清晰又符合 Kotlin 的编码规范。

5. 总结

通过本文我们了解了:

  • Kotlin 中的默认参数机制
  • 如何将函数作为参数传递
  • 如何为函数类型的参数设置默认实现

这些特性结合使用,可以显著提升代码的灵活性和可维护性,是编写高质量 Kotlin 代码的重要基础。

完整代码示例可在 GitHub 仓库 中找到。


如需进一步了解 Kotlin 的函数式编程特性,可参考官方文档或相关进阶教程。


原始标题:Using Function as Argument With Default Value in Kotlin