Kotlin破坏了五个以上的组成部分

Gav*_*vin 3 kotlin

我有一个正则表达式的结果,该表达式将七个捕获组返回到一个数组中。

我认为我将使用解构,而不是使用数组元素的下标来构造我的对象,问题是似乎我只能有五个组件。

一个最小的例子:

//  val (a, b, c, d, e) = listOf(1, 2, 3, 4, 5)
val (a, b, c, d, e, f, g) = listOf(1, 2, 3, 4, 5, 6, 7)
Run Code Online (Sandbox Code Playgroud)

编译器输出:

> Error:(70, 41) Kotlin: Destructuring declaration initializer of type
> List<Int> must have a 'component6()' function 
> Error:(70, 41) Kotlin: Destructuring declaration initializer of type 
> List<Int> must have a 'component7()' function
Run Code Online (Sandbox Code Playgroud)

有没有办法拥有五个以上的组件,或者这是最大值?

Wil*_*zel 6

该List接口仅定义了5个组件功能(作为扩展功能)。

您可以添加自己的组件功能作为扩展功能:

operator fun <T> List<T>.component6() = this[5]
operator fun <T> List<T>.component7() = this[6]
// ...
Run Code Online (Sandbox Code Playgroud)

现在可以使用:

val (a, b, c, d, e, f, g) = listOf(1, 2, 3, 4, 5, 6, 7)
Run Code Online (Sandbox Code Playgroud)

从文档:

而且,当然可以有component3()和component4()等等。

请注意,componentN()函数需要用operator关键字标记,以允许在解构声明中使用它们。


Zoe*_*Zoe 5

Kotlin 为这些组件析构函数定义了扩展方法。与数据类不同,这些不是无限生成的,每个项目一个。这也使它们有点危险,我稍后会谈到。

作为参考,定义在这里,KDoc可以在这里找到(component在列表中搜索。为了方便访问,这里是component1)。

正如您在源定义(以及与此相关的文档,但源使其更加可见)中看到的那样,只有 5 个方法 ( component1to component5),每个方法都调用get(n - 1),其中n是组件析构函数的 ID。

如果您想要更多,则必须按照以下模式自己定义它们:

inline operator fun <T> List<T>.componentN(): T {
    return get(N - 1)
}
Run Code Online (Sandbox Code Playgroud)

(或在另一个答案中建议的风格- 它们产生相同的结果。)

同样,其中 N 为 6 及以上,与您计划拥有的项目数量相匹配。

但是,我不会推荐这个。使用 for 循环对其进行迭代要容易得多,而且也不太容易出错。以这样的例子为例:

val (a, b, c, d, e) = listOf(1, 2, 3, 4)
Run Code Online (Sandbox Code Playgroud)

这将抛出一个 ArrayIndexOutOfBoundsException。但是,如果您有一个静态列表(并且知道您在做什么),则使用 with 进行破坏componentN是安全的。尽管如果您有一个主要是静态的列表,并且希望在未来获得灵活性,则可以使用数据类。这些也componentN为您生成函数,并将它们自己限制在您实际拥有的字段数量 - 这意味着在运行时没有异常,而是编译器错误。

如果您使用列表来启用除销毁之外的迭代,您还可以采用替代方法并定义一个operator fun iterator并返回项目列表。