共计 2280 个字符,预计需要花费 6 分钟才能阅读完成。
有时候您会想要将一个蕴含了多个字段的对象合成,以初始化几个独自的变量。为了实现这点,您能够应用 Kotlin 的解构申明性能。持续浏览本文以理解解构的应用、Kotlin 默认提供的类型、如何在您本人的类和您无法控制但认为将会从解构中受害的类中实现解构,以及这所有的外部实现。
用法
解构申明容许咱们应用以下形式定义 本地 值或变量:
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
fun play() {val (name, breed) = goodDoggo
println("Best doggo: $name")
}
应用解构能够十分不便地解决来自函数或汇合的数据:
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
fun getBestDoggoAndOwner(): Pair<Doggo, Owner> { ...}
// 数据来自 Pair 时的用法
fun play() {val (doggo, owner) = getBestDoggoAndOwner()}
fun play(doggoOwner: Map<Doggo, Owner>) {
// 在汇合和循环中应用解构
for((doggo, owner) in doggoOwner){...}
}
默认状况下,所有数据类均反对解构。
对于一个类的字段,您能够抉择只用其变量的子集:
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
data class Doggo(
val name: String,
val breed: String,
val rating: Int = 11
)
val (name, breed, rating) = goodDoggo
val (name, breed) = goodDoggo // 不须要时能够疏忽 rating 字段
解构不容许您抉择应用某个确切的字段;它永远应用前 x 个字段,这里的 x 是您所申明的变量数。这样做的毛病是很容易造成谬误,比方上面这段代码便可能造成意外的后果:
val (name, rating) = goodDoggo
rating 值事实上会持有 goodDoggo.breed 的值。您将会看到一个正告: “Variable name‘rating’matches the name of a different component” (‘rating’变量名匹配了名字不同的 component) 并且建议您将 rating 重命名为 breed。因为这个正告只存在于 IDE 中,而且不是编译器正告,您很容易就会留神不到它:
应用谬误的解构变量申明
如果您只须要一部分不间断的字段,能够应用 _ 代替那些您不感兴趣的字段,Kotlin 将会跳过它们。这样一来示例就会变成上面这样:
val (name, _, rating) = goodDoggo
外部原理
让咱们通过反编译后的数据类代码来看看到底产生了什么。本文将会只专一于那些为解构生成的函数,如果须要理解更多对于数据类的信息,请期待咱们将来的文章。
想要查看反编译后的 Java 代码,您能够在 Android studio 中应用 Tools -> Kotlin -> Show Kotlin Bytecode 而后点击 Decompile 按钮。
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
public final class Doggo {
@NotNull
private final String name;
@NotNull
private final String breed;
public Doggo(@NotNull String name, @NotNull String breed, int rating) {...}
...
@NotNull
public final String component1() {return this.name;}
@NotNull
public final String component2() {return this.breed;}
...
}
咱们看到编译器为主构造函数中申明的每个属性都生成了一个名为 componentN 的函数,这里的 N 是字段在主构造函数中的索引。
实现解构
正如咱们后面所看到的,解构的实现有赖于 componentN 函数。所以如果您想要为一个不反对解构的类增加解构性能,只须要实现对应的 componentN operator 函数即可。请确保您的函数应用了 operator 前缀。
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
class Doggo(
val name: String,
val breed: String
) {operator fun component1(): String = name
operator fun component2(): String = breed
...
}
为不属于您的类实现解构
Kotlin 容许您通过扩大函数为不属于您的类实现解构。举个例子,Map.Entry 是一个接口并且不反对解构。为了方便使用,Kotlin 为其创立了 component1() 和 component2() 函数,别离返回 Map.Entry 的键和值。
总结
当您须要将一个对象的字段拆解为值或者变量时,能够应用解构性能。它在外部是通过提供一系列的 componentN operator 函数实现的,所以当您认为能够通过此性能受害时,能够本人为您的类提供这些函数,便能够实现解构性能。