This is the 21st day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

First, data class

  • In Java, or in our usual Android development, in order to resolve the background staff to provide us with the interface of the returned Json string, we will according to the string to create a class or instance objects, in this class, only contains some data we need, and in order to deal with these data and the method of writing. Such classes are called data classes in Kotlin.

1. Keywords

The keyword for declaring a data class is: data

1.1. Declaration format

Data Class Name of the class (var param1: data type,...) {}Copy the code

or

Constructor (var param1: Data type = default,...)Copy the code

Description:

  • dataFor the statementData classesThe keyword must be written inclassKeyword before.
  • In the absence of a structure, curly braces{}Can be omitted.
  • At least one argument must exist in the constructor and must be usedvalorvarModification. This point is down hereData class featuresWe’ll talk about it in detail.
  • Default values for parameters are optional. (To instantiate a data class without arguments, use the default values.)

Ex. :

// Define a data class named Person (var name: String,val sex: Int, var age: Int)Copy the code

1.2. Established rules

  • Data classes also have conventions that make code more readable.

That is, when there are too many arguments in a constructor, the definition of one argument takes up one line for code readability.

Ex. :

data class Person(var param1: String = "param1", var param2: String = "param2", var param3 : String, var param4 : Long, var param5: Int = 2, var param6: String, var param7: Float = 3.14f, var param8: Int, var param9: String){ // exp . . . }Copy the code

1.3. What editors do for us

When we declare a data class, the editor automatically does something for the class, otherwise it’s much cleaner than Java. It automatically generates the following methods based on all attributes defined in the main constructor:

  • generateequals()Function andhasCode()function
  • generatetoString()Function byClass name (parameter 1 = value 1, parameter 2 = value 2,....)Constitute a
  • Automatically generated by the defined propertiesComponent1 (), Component2 (),... , componentN ()Function, which corresponds to the order in which attributes are declared.
  • The copy () function. Examples of how it works are shown below.

Where, when any of these functions is explicitly defined in the class body or inherits from its base type, the function is not generated

2. Features of data classes

Data classes have different features than Kotlin’s other classes. In addition to some features of other classes, it also has unique characteristics. And it is also the condition that the data class must meet:

  • The main constructor needs to have at least one argument
  • All arguments to the main constructor need to be marked with val or var;
  • Data classes cannot be abstract, open, sealed, or internal;
  • Data classes can implement interfaces, such as serialization interfaces, and can inherit from other classes, such as from a sealed class.

3. Illustrate its ratio with examplesJavaThe simplicity of

3.1 Comparison of data classes

Kotlin version:

data class User(val name : String, val pwd : String)
Copy the code

Java version:

public class User { private String name; private String pwd; public User(){} public User(String name, String pwd) { this.name = name; this.pwd = pwd; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } @Override public String toString() { return "User{" + "name='" + name + ''' + ", pwd='" + pwd + ''' + '}'; }}Copy the code

Analysis: To achieve the same function, in terms of the amount of code, Koltin has many fewer lines of code than Java, and is much simpler than Java.

3.2. Modify data class attributes

Example: Modify the name attribute of the User class

Kotlin version:

  • KoltinTo modify the attributes of a data class, use its uniquecopy()Function. This is used to modify some attributes, but leave others unchanged
val mUser = User("kotlin","123456")
println(mUser)
val mNewUser = mUser.copy(name = "new Kotlin")
println(mNewUser)
Copy the code

The output is:

User(name=kotlin, pwd=123456)
User(name=new Kotlin, pwd=123456)
Copy the code

Java version:

User mUser = new User("Java","123456");
System.out.println(mUser);
mUser.setName("new Java");
System.out.println(mUser);    
Copy the code

The output is:

User{name='Java', pwd='123456'}
User{name='new Java', pwd='123456'}
Copy the code

Kotlin uses its own copy() function to change property values, while Java uses setXXX() to change property values

4. Deconstruct the statement

  • As I mentioned earlier,KotlinTo define a data class, the system will automatically generate according to the number of parameters by defaultcomponent1() ... componentN()Function. its. ,componentN()Functions are used to deconstruct declarations
val mUser = User("kotlin","123456")
val (name,pwd) = mUser
println("name = $name\tpwd = $pwd")
Copy the code

The output is:

name = kotlin   pwd = 123456
Copy the code

5. Standard data classes in the system standard library

  • The standard library provides Pair and Triple. In many cases, though, naming data classes is a better design choice because they make the code more readable by providing meaningful names for properties.
  • In fact, the source code of these two classes is not much, so post the source code of this class to analyze

5.1 Source code analysis

@file: kotlin.jvmName ("TuplesKt") package kotlin // public data class Pair<out A, Out B>(public val first: A, public val second: B) : Serializable {// toString() public override fun toString(): String = "($first, $second)"} // convert public infix fun <A, B> a.dot (that: B): Public fun <T> Pair<T, T>.tolist (): List<T> = listOf(first, second) public data class Triple<out A, out B, out C> A, public val second: B, public val third: C): Serializable {// toString() public override fun toString(): String = "($first, $second, $third)"} public fun <T> Triple<T, T, T>.tolist (): List<T> = listOf(first, second, third)Copy the code

The standard library provides two standard data classes, Pair class and Triple class. Among them:

  • It’s implemented in both classestoList()Methods andtoString()Methods.
  • to()Method isPair classUnique, function is parameter conversion
  • Pair classYou need to pass two parameters,Triple classThree arguments need to be passed.

5.2, usage,

Val pair = pair (1,2) val triple = triple (1,2) Println (pair.tolist ()) // converts toList println(pair.to(3)) // converts toList println(pair.to(3)) // The Pair class is unique: it replaces the second argument in the Pair classCopy the code

The output is:

(1, 2) (1, 2, 3) [1, 2] [1, 2, 3] (1, 2)Copy the code

Two, sealing class

Sealed classes are used to represent restricted class inheritance structures. If you are not familiar with Kotlin’s class inheritance, please refer to my previous article, Kotlin — Intermediate (4) : Inheritance classes in detail.

What is a restricted class inheritance structure

  • A restricted class inheritance structure is one in which a value in a class can be of a limited number of types and not of any other type.
  • This restricted class inheritance structure is, in a sense, an extension of enumerated classes. But we knowKotlinEnumeration constants in the enumeration class are limited because only one instance of each enumeration constant can exist. If theKotlinSee my other article for more information about the enumeration classes inKotlin — Intermediate part (5) : Enumeration class (Enum), Interface class (details).
  • Unlike enumerated classes, however, a subclass of a sealed class can have multiple instances of containable state.
  • In other words, a sealed class contains a limited set of classes, because all the classes in it inherit from the sealed class. But it and other inherited classes (openThe difference is that sealed classes can not be inherited outside of this file, effectively protecting the code. However, the extension of the subclass of its sealed class can be anywhere in the program, that is, it can no longer be unified under the file.

The above content is the characteristics of the sealing class, please look at it in detail, xiao Sheng will carry out a detailed analysis of these points.

2. Keywords

Defines the keyword of the sealed class: sealed

2.1 Declaration format

sealed class SealedExpr()
Copy the code

Note: Sealed classes cannot be instantiated

namely

Val mSealedExpr = SealedExpr()Copy the code

Since a sealed class cannot be instantiated, how do we use it, or what does it do? Keep reading

3, the role of sealing class and its detailed usage.

3.1,

Used to represent a restricted class inheritance structure.

Ex. :

sealed class SealedExpr{ data class Person(val num1 : Int, val num2 : Int) : SealedExpr() object Add : SealedExpr() // Object Minus: SealedExpr() // singleton} // Its subclasses can be defined outside the enclosing class, but must only be defined inside the enclosing class until v1.1 in the same fileCopy the code

Analysis: that is, the defined subclasses must inherit from the sealed class, representing a restricted set of classes

3.2. Differences with ordinary inherited classes

  • We know that ordinary inherited classes useopenKeyword definition, into which classes in the project can be integrated. If you areKoltinThe inheritance class of the. Please see my other articleKotlin — Intermediate part 4: Inheritance classes in detail.
  • The subclass of the sealed class must be inside the sealed class or must exist in the same file of the sealed class. This is the point of effective code protection mentioned above.

3.3, and enumeration class difference

  • Only one instance can exist for each enumeration constant in an enumeration class. A subclass of a sealed class can have multiple instances.

Ex. :

val mPerson1 = SealedExpr.Person("name1",22)
println(mPerson1)

val mPerson2 = SealedExpr.Person("name2",23)
println(mPerson2)

println(mPerson1.hashCode())
println(mPerson2.hashCode())
Copy the code

The output is:

Person(name=name1, age=22)
Person(name=name2, age=23)
-1052833328
-1052833296
Copy the code

3.4 class extension instances of its subclasses

  • inKotlinSupport extended functionality, its andC#,GoThe language is similar. This is aJavaDon’t have.

To demonstrate that the extension of the sealed subclass can be anywhere in the project, you can download the source code. A link to the source code is provided at the end of the article. Ex. :

SealedClass SealedExpr{data class Person(val name: String, val age: Int) : // SealedClass SealedExpr{data class Person(val name: String, val age: Int) : SealedExpr() object Add : SealedExpr() companion object Minus : SealedExpr() } object NotANumber : Fun <T> sealedexpr.add. Add (num1: T, num2: T) : Int{return 100} fun main(args: Array < String >) {println (SealedExpr. Add. Add (1, 2))}Copy the code

The output is:

100
Copy the code

Note: the above extension function does not have any significance, just to show you that the extension of the sealed class subclass is not limited to the same as the sealed file this function.

3.5, the use of sealing benefits

  • Valid protection code (reasons explained above)
  • In the use ofwhenIf you can verify that the statement covers all cases, you do not need to add another statement to the statementelseThe clause.

Ex. :

sealed class SealedExpr{
    data class Person(val name : String, val age : Int) : SealedExpr()
    object Add : SealedExpr()
    companion object Minus : SealedExpr()
}

object NotANumber : SealedExpr()

fun eval(expr: SealedExpr) = when(expr){
    is SealedExpr.Add -> println("is Add")
    is SealedExpr.Minus -> println("is Minus")
    is SealedExpr.Person -> println(SealedExpr.Person("Koltin",22))
    NotANumber -> Double.NaN
}
Copy the code

The output is:

is Minus
Copy the code

Third, summary

In an actual project, the usefulness of data classes (data) is a lot of, because, in the development of APP developers tend to be based on the background provided by the interface of the returned json and generates an entity class, now we learn the data after the class, don’t have to write so much like Java code, even if is to use editor provides methods to automatically generate. But it saves us a lot of time in terms of the amount of code, and it’s much simpler. Why not? The case of sealed classes is not very common in real development. Sealing classes are used only when specific requirements are needed. Of course we still have to learn.