10

我正在使用 Kotlin 原生库对象在 Kotlin 中工作,该对象包含一个方法,其.nameIsMuchTooLongAndIsStillNotClear. 以类似于 的方式typealias,我想为该方法创建一个别名,因此我可以将其称为 something .shortAndClear。为了使事情稍微复杂化,这些函数有几个参数,其中许多具有我不希望在包装器中预处理的默认值。经过进一步研究,似乎扩展功能仍然是要走的路。

要使用一个易于测试的示例函数,假设我想为其创建一个别名类型的扩展String.startsWith名为String.beg. 我可以轻松获得以下解决方案:

inline fun String.beg(prefix: CharSequence, ignoreCase: Boolean = false) = startsWith(prefix, ignoreCase)   // works ok

但是,这似乎要求我列出所有参数及其默认值,并且对每个重载都这样做。(有问题的真正方法签名要长得多,有更多的默认值。)本着“不要重复自己”的精神,有没有一种方法可以使用函数引用String::startsWith这样我就不必枚举所有参数? 我尝试了几种形式,但它们都不起作用:

// none of these work:
fun String.beg = String::startsWith
fun String.beg = this::startsWith
val String.beg: (CharSequence, Boolean) -> Boolean = String::startsWith
4

2 回答 2

8

目前没有办法完全实现你想要做的事情。如果要保留默认参数,则必须这样做(如您所说):

fun String.beg(prefix: CharSequence, ignoreCase: Boolean = false) = startsWith(prefix, ignoreCase)
// Or if you know that ignoreCase will be always false, you can pass the value directly to "startsWith()
fun String.beg(prefix: CharSequence) = startsWith(prefix, false)

相反,如果您没有默认参数,或者您不关心在调用函数时是否必须传递默认值,则可以使用函数引用。

val String.beg: (CharSequence, Boolean) -> Boolean get() = this::startsWith
// If the parameters can be inferred, you can avoid the type specification.
// In this case it won't compile because there are several combinations for "startsWith()".
val String.beg get() = this::startsWith

在这种情况下,您不能指定参数的默认值,因为beg它是一个 lambda。

从 Kotlin 1.2(目前处于测试阶段)开始,您可以避免this在函数引用上指定。上面写的相同示例,但在 Kotlin 1.2 中:

val String.beg: (CharSequence, Boolean) -> Boolean get() = ::startsWith
// If the parameters can be inferred, you can avoid the type specification.
// In this case it won't compile because there are several combinations for "startsWith()".
val String.beg get() = ::startsWith
于 2017-10-08T15:02:10.137 回答
0

您还可以使用导入别名,例如:

import kotlin.text.startsWith as beg

fun main() {
    "foo".beg("fo")
    "bar".beg('B', true)
}
于 2020-11-02T09:47:18.100 回答