ComponentN method
Let {name,isCheck} = option, you can extract the name and isCheck attributes from the option object. Instead of using let name = option.name, the deconstructed syntax simplifies the code further. Does Kotlin, a rising star, have this feature? Yes, Kotlin has one, too. It’s called the componentN method. Let’s get right to the code:
class User(val username: String, val age: Int) {
operator fun component1(a): String {
return username
}
operator fun component2(a): Int {
return age
}
}
fun main(a) {
val user = User("lqr".18)
println("username = ${user.username} , age = ${user.age}")// username = lqr , age = 18
val (username, age) = user
println("username = $username , age = $age") // username = lqr , age = 18println(user)// com.charylin.kotlinlearn.User@2f0e140b
}
Copy the code
Component1 () and Component2 () can be extracted from object by writing val (arg1, arg2) in object, and there is no limit to the return value type for componentN.
Kotlin’s componentN method calls componentN() sequentially to assign values to variables, so there’s a difference!!
Data Classes
You might think Kotlin is pushing developers a little too hard to achieve syntactic features like “ES6 deconstruction” by writing componentN methods, and yes, if that’s all there is to it, that would be embarrassing. Ok, Kotlin’s Data class automatically generates componentN methods for objects. Data classes also generate toString(), copy(), and other methods by default:
data class User(val username: String, val age: Int)
fun main(a) {
val user = User("lqr".18)
println("username = ${user.username} , age = ${user.age}") // username = lqr , age = 18
val (username, age) = user
println("username = $username , age = $age") // username = lqr , age = 18
println(user) // User(username=lqr, age=18)
}
Copy the code
Visible, the use of data class without their own handwriting componentN method, put aside the “ES6 deconstruction” syntax, we look at the data class (Data class, as the name implies, data class is designed to store data, The most important thing to focus on is the data itself, so when we declare a data class, we just need to write the member attributes, and leave the rest to the data class, which will handle the toString(), copy() and other methods. The componentN method is just a way for developers to extract data from it.
From a Java developer’s point of view, data classes were created to replace Javabeans.
Remember intarray.withIndex ()? Iterable
>
// _Arrays.kt
/** * Returns a lazy [Iterable] of [IndexedValue] for each element of the original array. */
public fun IntArray.withIndex(a): Iterable<IndexedValue<Int> > {return IndexingIterable { iterator() }
}
// IndexedValue.kt
/**
* Data class representing a value from a collection or sequence, along with its index 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)
Copy the code
For (index, value) in intarray.withindex (); for (index, value) in intarray.withindex ();
val intArray = intArrayOf(1.2.3.4.5)
for ((index, value) in intArray.withIndex()) {
println("index = $index, value = $value")}Copy the code
AllOpen and noArg plug-ins
While data classes have many useful syntactic sugar features compared to Javabeans, they also have their drawbacks:
data class
The default is final and cannot be inherited.data class
There is no no-argument constructor by default.
Decompile the data Class User class into Java code with the Show Kotlin Bytecode tool.
public final class User {
@NotNull
private final String username;
private final int age;
@NotNull
public final String getUsername(a) {
return this.username;
}
public final int getAge(a) {
return this.age;
}
public User(@NotNull String username, int age) {
super(a);this.username = username;
this.age = age;
}
@NotNull
public final String component1(a) {
return this.username;
}
public final int component2(a) {
return this.age;
}
@NotNull
public final User copy(@NotNull String username, int age) {
Intrinsics.checkParameterIsNotNull(username, "username");
return new User(username, age);
}
@NotNull
public String toString(a) {
return "User(username=" + this.username + ", age=" + this.age + ")";
}
public int hashCode(a) {... }public boolean equals(@Nullable Object var1) {... }}Copy the code
Some development scenarios, such as databases, require data classes to be parameterless constructors or inheritable. This is not solvable to the data class itself, but it can be solved with the allOpen and noArg plug-ins. Add a no-argument constructor (noArg) and remove final restrictions (allOpen) at compile time.
1. Declare the annotation class
Write an annotation class with an arbitrary name that can be used later:
annotation class Poko
Copy the code
2. Configure Gradle scripts
In the gradle script file of the project, configure allOpen and noArg plugins:
buildscript {
ext.kotlin_version = '1.3.72'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// step1. dependency plugin
classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"}}// Apply the plugin
apply plugin: "kotlin-noarg"
apply plugin: "kotlin-allopen"
// Step3. Configure plug-ins
noArg {
// invokeInitializers = true // ture: init{}; False (default) : init{} code is not executed
annotation("com.charylin.kotlinlearn.annotation.Poko")
}
allOpen {
annotation("com.charylin.kotlinlearn.annotation.Poko")}Copy the code
In Gradle scripts, noArg and allOpen configuration items use the previous annotation class Poko. You just need to configure the full path of the annotation class Poko.
3. Use annotation classes
Using the annotation class Poko on the Data class:
@Poko
data class User(val username: String, val age: Int)
Copy the code
Add the allOpen and noArg plugins to the rebuild project, and then decompile the User Java code.
public class User {...public User(@NotNull String username, int age) {
Intrinsics.checkParameterIsNotNull(username, "username");
super(a);this.username = username;
this.age = age;
}
public User(a) {}}Copy the code
As you can see, the final constraint is removed and a no-argument constructor is added. As mentioned earlier, these two plug-ins modify the data class at compile time, which means that we cannot use the no-argument constructor or inherit the data class before compile time (i.e. coding), but we can handle this problem through reflection.