componentN 方法

大前端 es6 中有一个解构的语法特性我很是喜欢,通过类似 let {name,isCheck} = option 的写法就可以从 option 对象中提取出 name 和 isChegithub中文官网ck 属性,而不再是使用 let name = option.name 这种写法,解构的语法让代码得以更进一步的简化,那么作为后起之秀的 Kotlin 是否也有这种特性呢?没错,Kotlin 也有(注意:两者还是有区别的),它就是 componentN 方法 ,我们直接来看代码:

class User(val username: String, val age: Int) {
operator fun component1(): String {
reelementary怎么读音turnjetbrains clion username
}
opkotlin下载erator fun compongiticomfortent2(): Int {
return age
}
}
fun main() {
val user = User("lqr", 18)
println("username = ${user.username} , age = ${user.age}") // username = lqr , age = 18
val (username, age) = user
println("username = $usernaelementary是什么意思me , age = $age") // username = lqr , age = 18
println(Elementuser) // com.cKotlinharylin.kjetbrains有哪些产品otlinlearn.User@2f0e140b
}

使用 val (arg1, arg2) in objecgithubt 这种写法,就可以从 object 对象中提取出 component1() 和 component2() 的返回jetbrains是什么软件结果,而且 componentN 方法 的返回值类型是没有限制的。

es6 的解构语法是根据变量名提取属性值的,而 Kotlin 的elements componentN 方法 则是按顺序调用 componentN() 给变量赋kotlin发音值,所以这两者还是有差别的!!!

数据类(data class)

你可能会觉得 Kotlin 为了达到类似 “es6 解构” 的语法特性,对开发者的要求有点高啊,还要自己编写 componentN 方法 ,是的,如果就只是这样的话,那很糗唉,还好,Kotlin 中的 数据类(data class) 就可以自动为对象生成 componentN 方法 ,不仅如此,data class 还会默认生成 toString()copy() 等方法:

data class User(vgradle是什么al usgiti轮胎是什么品牌ername: String, val age: Int)
fun main() {
vgradle翻译al user = User("lqr", 18)
pelement是什么牌子rintln("username = ${user.username} , age = ${user.age}") // usernamegiticomfort是什么轮胎品牌 = lqr , age = 18
val (usernamegiticomfort, age) = user
println("username = $ujetbrains ideasernagitlabme , age = $age") // username = lqr , age = 18
println(user) // User(username=lqr, age=18)
}

可见,使用 data class 就无须自己手写 componentN 方法 了,抛开 “es6 解构” 语法,我们来看 数据类(data class) ,顾名思义, data class 被设计出来就是为了存储数据的,最核心最应该被关注的就是数据本身,所以在jetbrains clion声明 data class 时,我们只需jetbrains激活码要把成员属性写好,剩下的elementary是什么意思交给 data class ,它会自己处理好 toString()copy() 等方法,componentN 方法 也只是为了方便开发者提取其中的数据而已。

从 Java 开发者的角度来看,数据类(data class) 的诞生就是为giticomfort了取代 JavaBean 的。

还记得 IntArray.withIndex() 吗?它的返回值 Iterjetbrains中文版able<IndexedValueGit<Int&github是干什么的gt;> 中泛型element是什么牌子IndexedValue 就是 data class

// _Arrays.kt
/**
* Returns a lakotlin协程zy [Iterable] of [IndexedValue] for each element of the originalgiticomfort是什么轮胎品牌 array.
*/
public fun IntArray.withIndex(): Iterable<IndexedValue<ElementInt>> {
return IndexingIterable { iteratorgitv() }
}
//jetbrains怎么读 IndexedValkotlin为什么流行不起来ue.kt
/**
* Data class reprelement什么意思中文esenting a value from a collection or sequence, along with its igradle配置ndjetbrains有哪些产品ex in that collection or sequence.
*
* @property value the underlying value.
* @property index the index of the value in the collection or sequence.
*/
public data class IndexedValue<out T>(public val index: Int, public val value: T)

因此,在 for 循环中,才会有 (index, value) in intArray.withIndex() 这种写github中文官网法,本质上就是使用了giti data class 默认生成的 componentN 方法

val intArray = intArrayOf(1, 2, 3, 4, 5)
for ((index, vaJetBrainslue) in intArray.witkotlin极简教程hIndex()) {
println("index = $index, value = $value")
}

allOpen 和 noArg 插件

相比 JavaBean,虽然 data class 有很多好用的语法糖特性,但也有其不足的地方:

  • data class 默认 final,无法被继承。
  • data class 默认没有无参构造函数。

借助 Show Kotlin Bytecode 工具,将上面的 data class User 类反编译成 Java 代码,发现确实有这 2 点问题:

public final class User {
@Noelement是什么牌子tNull
private final String username;
private final int age;
@NotNull
public final String getUsername() {
return this.username;
}
public final int getAge() {
return this.age;
}
public User(@NotNull String username, int age) {
super();
thiselement是什么牌子.username = usernjetbrains ideaame;
this.age = age;
}
@NotNjetbrains中文版ull
publigradle是什么c final String component1() {
return this.username;
}
public final int compongradle版本ent2() {
return this.age;
}
@NotNull
public final UserGit copy(@NotNull String username, int age) {
Intrinsics.checkParameterIsNotNull(username, "username");
regiteeturn new User(username, agjetbrains怎么读e);
}
@NotNull
public String toString() {
return "User(ukotlin面试题sername=" + this.username + ", age=" + this.age + ")";
}
public injetbrains官网t hashCode() { ... }
public boolean equals(@Nullable Object var1) { ... }
}

在一些开发场景下(如数据库),会要求数据类必须要有无jetbrains idea参构造函数或可继承,这对 data cgiteelass 本身来说是无解的,但可以jetbrains什么意思借助 allOpennoArg 插件来解决这个问题,让 data class 在编译期增加无参构造JetBrains器(noArg 插件),并去除 final 限制(allOpen 插件),集成这 2 个插件的步骤如下:

1. 声明注解类

编写一个注解类,名字随便,后续用得到:

annotation class Poko

2. 配置 Gradle 脚本

在工程的 gradle 脚本文件中,配置 akotlin教程llOpen 和 noArggithub 插件:kotlin ?.作用

buildscript {
ext.kotlin_version = '1.3.72'
repositories {
mavenCentrjetbrains激活码al()
}
dependencies {
classpath "org.jetbrains.kotgitlablin:kotlin-gradle-plugin:$kotlin_version"
// Step1. 依赖插件
classpath "org.jetbrains.kotlin:kotlin-noarg:$elementanimationkotlin_version"
classpath "Kotlinorg.jetbrains.kotlin:kotlin-allopen:$kotlin_versjetbrains clionion"
}
}
// Step2. 应用插件
apply plugin:github中文官网 "kotlin-noarg"
apply pluggradle homein: "kotlin-allopen"
//github Step3. 配置插件
noArg {
annotation("com.charylin.kotlinlearn.annotation.Poko")
}
allOpen {
annotation("com.charylin.kotlgradle翻译inlearn.annotation.Poko")
}

Gragradle教程dle 脚本中,noArgallOpen 配置项就用到了前面的注解类 Poko,只需要把注解类 Poko 的全路径配置进去就好了。

3.使用注解类

data class 上使用giticomfort注解类 Poko :

@Poko
data class User(vagradlel username: String, val age: Int)

经过上述步giticomfort骤便完成了 allOpennoArg 插件的集成和使用,接下来jetbrains激活码就是 rebuild projectKotlin,然后再反编译看看 User 类的 Java 代码:

public class User {
...
public User(@NotNull String username, int age) {
Ikotlin ?.作用ntrinsics.checelementarykParkotlin极简教程ameterIsNotNull(username, "username");
super()github;
this.username = username;
this.age = age;
}element什么意思中文
public User() {
}
}

可以看到,final 限制去除了,也多了一个无参jetbrains什么意思构造器。前面也提到了,这 2 个插件是在编译期对 data class 进行修改,也就是说,我们无法在编译期之前kotlin面试题(也就是 coding 的时候)去使用该无参构造器或继element什么意思中文承该gradle下载 data class,不过呢,可以通过反射来处理这个问题。

Kotlin - 数据类