【解密 Kotlin 扩展函数】命名参数和默认值(十三)
导读大纲
- 1.0.1 命名参数
- 1.0.2 默认参数值
- 上一节讲述如何自定义 joinToString 函数来代替集合的默认字符串表示
- 文末遗留下几个待优化问题–传送门
1.0.1 命名参数
-
我们要解决的第一个问题涉及函数调用的可读性
- 例如,请看下面的joinToString调用: joinToString(collection," “,” “,”.")
- 你能知道所有这些字符串对应的参数是什么吗?
- 你能知道这些元素是用空格还是点分隔的?
- 如果不查看函数的签名,就很难回答这些问题
- 也许你的集成开发环境能帮到你,但单纯从调用代码中是看不出来的
- 也许你的集成开发环境能帮到你,但单纯从调用代码中是看不出来的
- 例如,请看下面的joinToString调用: joinToString(collection," “,” “,”.")
-
这个问题在布尔(Boolean)标志中尤其常见
- 为了解决这个问题,一些 Java 编码风格建议
- 创建枚举类型,而不是使用布尔类型
- <1> 还有一些参数甚至需要在注释中明确指定参数名
- 比如下面的代码块中使用/* separator */ 来指定对应的参数名
- <2> 有了 Kotlin, 我们可以优雅地解决, 因为 Kotlin 支持命名参数
- 为了解决这个问题,一些 Java 编码风格建议
=================================== <1>
/* Java */
joinToString(collection, /* separator */ " ", /* prefix */ " ",
/* postfix */ ".");
==================================== <2>
fun main() {
val list = listOf(1, 2, 3)
println(joinToString(list, separator = "; ", prefix = "(", postfix = ")"))
// (1; 2; 3)
}
- 调用 Kotlin 编写的函数时,可以指定传递给函数的部分(或全部)参数的名称
- 如果指定传递给函数的所有参数的名称,甚至可以更改它们的传参顺序
- 如果指定传递给函数的所有参数的名称,甚至可以更改它们的传参顺序
fun main() {
val list = listOf(1, 2, 3)
println(joinToString(separator = "; ", postfix = ")", prefix = "(", collection = list ))
// (1; 2; 3)
}
- 如果重新命名被调用函数的参数
- IntelliJ IDEA 和 Android Studio可以使显式编写的参数名称保持最新
- **使用"重命名"(Rename)或"更改签名"(Change Signature)**操作
- 这两种操作都可以通过**右键单击函数名并选择"重构(Refactor)"**选项
- 这两种操作都可以通过**右键单击函数名并选择"重构(Refactor)"**选项
1.0.2 默认参数值
-
Java 的另一个常见问题是某些类中的重载方法过多
- java.lang.Thread及其八个构造函数
- 提供重载可能是为了向后兼容、方便 API 用户或其他原因
- 但最终结果都是一样的: 重复
- 参数名称和类型一次又一次地重复
- 如果要彻底的话,还得在每个重载中重复大部分文档
- 同时,如果调用一个省略某些参数的重载
- 并不总是很清楚它们使用哪些参数
- java.lang.Thread及其八个构造函数
-
在 Kotlin 中,由于可以在函数声明中指定参数的默认值
- 因此通常可以避免创建重载
-
在大多数情况下,字符串可以用逗号分隔,不需要任何前缀或后缀
- <1> 因此,我们可以将这些参数设为默认值
- <2> 可以调用函数的所有参数, 也可以省略部分参数以使用对应的默认值
- 可以看到三种不同形式的参数传递都是ok的
fun <T> joinToString(
collection: Collection<T>,
separator: String = ", ", // <1>
prefix: String = "", // <1>
postfix: String = "" // <1>
) : String {
val result = StringBuilder(prefix)
for ((index, elem) in collection.withIndex()){
if (index > 0) result.append(separator)
result.append(elem)
}
result.append(postfix)
return result.toString()
}
fun main() {
val list = listOf(1, 2, 3)
println(joinToString(list, ", ", "", "")) // <2>
println(joinToString(list)) // <2>
println(joinToString(list, separator = "; ")) // <2>
}
========================================
1, 2, 3
1, 2, 3
1; 2; 3
- 众所周知,Java中是没有默认参数值的概念
- 那么如何在Java中调用具有默认参数的Kotlin函数呢?
- 下一节将进入一个新的专题系列:Kotlin 与 Java 的互操作