注意我已经查看了以下问题/答案,以便在没有任何运气的情况下解决问题。 Call Java Varargs Method from Kotlin - 这个参数列表末尾有一个varargs参数,但我的问题是在参数列表的开头处理varargs。 Kotlin: Convert List to Java Varargs - 同样的。其他搜索产生相同的结果。这些是我能找到的最接近的。
我使用单个字符分隔符调用Kotlin String.split
方法。
这是vararg
方法,其中vararg
参数是多个参数中的第一个。该方法的定义如下:
public fun CharSequence.split(vararg delimiters: Char,
ignoreCase: Boolean = false,
limit: Int = 0): List<String>
当我调用下面的方法时,它编译得很好:
fun String.splitRuleSymbol() : String = this.split(':') //ok
但是当我尝试添加ignoreCase
和limit
参数时,我遇到了问题:
fun String.splitRuleSymbol() : String = this.split(':', true, 2) //compiler error
我得到的错误是......
使用提供的参数不能调用以下任何函数:
public fun CharSequence.split(vararg delimiters:String,ignoreCase:Boolean = ...,limit:Int = ...):kotlin.text中定义的列表
public fun CharSequence.split(vararg delimiters:Char,ignoreCase:Boolean = ...,limit:Int = ...):kotlin.text中定义的列表
对我而言,拥有vararg
参数后跟其他参数有点奇怪,但这不是重点。如果我将其称为如下,它可以正常工作:
// both of the following compile
fun String.splitRuleSymbol() : String =
this.split(delimiters = ':', ignoreCase = true, limit = 2)
fun String.splitRuleSymbol2() : String =
this.split(';', ignoreCase = true, limit = 2)
有没有办法将vararg Char
传递给此方法,而无需使用参数名称ignoreCase
和limit
限定其他两个参数?可以编译器没有告诉剩下的参数不是Char
?
我已经尝试了the spread operator以及其他一些方法,其中没有一个可行:
//compiler errors on all these
this.split(*':', true, 2) //using the "spread" operator
this.split(*charArrayOf(':'), true, 2)
this.split(*mutableListOf(':'), true, 2)
this.split(*Array<Char>(1) { ':' }, true, 2)
是的,其中一些看起来很荒谬,我知道。但是,有没有办法避免冗长的替代方案?
PS 当我正在制定我的问题时,我找到了另一个编译的表达式。
this.split(':', limit = 2)
这不那么冗长,因为我不需要更改默认的ignoreCase
参数,所以它更接近我正在寻找的内容。
答案 0 :(得分:3)
您的观察结果是正确的。只能通过使用命名参数传递vararg
参数之后的参数,否则会遇到模糊问题(对于一个简单的例子,假设所有参数都是Any
类型)
我现在能找到的最佳来源是book。
vararg参数通常是最后一个参数,但并不总是如此。如果在vararg之后还有其他参数,则必须使用命名参数传递参数
编辑:@Les找到了一个很好的来源,请参阅their answer。
答案 1 :(得分:3)
感谢zsmb13,我能够在Kotlin Specification中找到以下段落(&#34;函数和Lambda&#34;
)只有一个参数可以标记为vararg。如果是vararg参数 不是列表中的最后一个,以下参数的值可以 使用命名参数语法传递,或者,如果参数具有 函数类型,通过在括号外传递lambda。
我冒昧地补充说,#34;可以通过&#34;应改为&#34;必须通过&#34;因为编译器不会允许,否则。
注意 lambda部分很有意思,因为规范通常只允许lambda在 last 参数时移动到括号外。规范的措辞暗示lambda可以在vararg
参数之后的任何地方,但是实验表明它是canont,即它必须是最后一个参数才能有资格移出括号。
fun main(args: Array<String>) {
test("hello", limit = 1, ic = false, delims = ';') { } //ok
//test2("world", limit = 1, ic = false, delims = ';') { } //error
test2("world", f = {}, limit = 1, ic = false, delims = ';') //ok
test("hello world", ';', limit = 1, ic = false) {} //ok
}
fun test(vararg delims: Char, ic: Boolean, limit: Int, f: () -> Unit) {}
fun test2(vararg delims: Char, f: () -> Unit, ic: Boolean, limit: Int) {}
答案 2 :(得分:2)
可以使用扩展运算符在命名表单中传递可变数量的参数(vararg):
fun foo(vararg strings: String) { /* ... */ }
foo(strings = *arrayOf("a", "b", "c"))
foo(strings = "a") // Not required for a single value
请注意,调用Java函数时不能使用命名参数语法,因为Java字节码并不总是保留函数参数的名称。