Genius is 1% inspiration and 99% perspiration, but that 1% inspiration is the most important, even are more important than that 99% perspiration – Edison

In the previous several chapters, a detailed explanation of Koltin Interface (Interface), enumeration (Enmu). In today’s chapter, data classes and containment classes are explained in detail

directory

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.1. Keywords

The keyword for declaring a data class is: data

1.1.1. Declaration format

data classThe name of the class(varParam1: Data type...) {}

Copy the code

or

data classClass name visibility modifierconstructor(varParam1: Data type = default value...)

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.)

Example: Define a data class named Person

data class Preson(var name : String,val sex : Int.var age : Int)

Copy the code

1.1.2 conventional provisions

  • 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){

    // something...

}

Copy the code

1.1.3 what the editor does 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

1.2. Characteristics 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.

1.3. Use examples to illustrate simplicity

1.3.1 Comparison of data classes

Kotlin version:

data class User(var name : String.var pwd : String)

Copy the code

Java version:

public class User {

    private String name;

    private String pwd;



    public User(a){}



    public User(String name, String pwd) {

        this.name = name;

        this.pwd = pwd;

    }



    public String getName(a) {

        return name;

    }



    public void setName(String name) {

        this.name = name;

    }



    public String getPwd(a) {

        return pwd;

    }



    public void setPwd(String pwd) {

        this.pwd = pwd;

    }



    @Override

    public String toString(a) {

        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.

1.3.2. Modify data class attributes

Example: Modify the name attribute of the User class

Kotlin version:

Koltin modifies the attributes of the data class, and if the attributes are modified with val, you can only use its own copy() function. It does this by modifying some properties, but leaving others unchanged. If you use var, you can also use Setter() functions, just like in Java

val mUser = User("kotlin"."123456")

println(mUser)

mUser.name = "first new kotlin"

println(mUser)

val mNewUser = mUser.copy(name = "second new Kotlin")

println(mNewUser)

Copy the code

The output is:

User(name=kotlin, pwd= 123456).

User(name=first new kotlin, pwd= 123456).

User(name=second 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

1.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

1.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

1.5.1 Source code analysis

@file:kotlin.jvm.JvmName("TuplesKt")

package kotlin



// The comments in the source code are removed

public data class Pair<out A, out B>(

        public val first: A,

        public val second: B) : Serializable {



    / / the toString () method

    public override fun toString(a): String = "($first.$second)"

}



/ / conversion

public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)



// Convert to a List collection

public fun <T> Pair<T, T>.toList(a): List<T> = listOf(first, second)



// The comments in the source code are removed

public data class Triple<out A, out B, out C>(

        public val first: A,

        public val second: B,

        public val third: C ) : Serializable {



    / / the toString () method

    public override fun toString(a): String = "($first.$second.$third)"

}



// Convert to a List collection

public fun <T> Triple<T, T, T>.toList(a): 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.

1.5.2, usage,

val pair = Pair(1.2)        / / instance

val triple = Triple(1.2.3)  / / instance

println("$pair \t $triple"// Print: the respective toString() methods are called

println(pair.toList())      // Convert to a List collection

println(triple.toList())    // Convert to a List collection

println(pair.to(3))         // The Pair class is unique: it replaces the second argument in the Pair class

Copy the code

The output is:

(1.2)      (1.2.3)

[1, 2]

[1, 2, 3]

((1.2), 3)

Copy the code

Two, sealing class

Sealed classes are used to represent restricted class inheritance structures

2.1. 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.
  • 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 a subclass of its sealed class can be anywhere in the program, that is, not under the same file.

2.2. Keywords

Defines the keyword of the sealed class: sealed

The statement formats

sealed class SealedExpr(a)

Copy the code

PS: Sealed classes cannot be instantiated

namely

val mSealedExpr = SealedExpr()  // This code is an error, the compiler will directly fail to compile.

Copy the code

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

2.3 Functions and usage

2.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()   // Singleton mode

object Minus : SealedExpr() // Singleton mode

}



// Subclasses can be outside the sealed class, but must be in the same file. Previously, 'V1.1' could only be defined inside a sealed class

object NotANumber : SealedExpr() 

Copy the code

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

2.3.2. The difference between ordinary inherited classes and ordinary inherited classes

  • Used by normal inherited classesopenKeyword definition to which all classes in the project can be inherited.
  • 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.

2.3.3, and enumeration classes

  • 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

2.3.4 Class extension instance of subclass

Ex. :

// It exists in the SealedClassDemo.kt file

sealed class SealedExpr{

    data class Person(val name : String, val age : Int) : SealedExpr()

    object Add : SealedExpr()

    companion object Minus : SealedExpr()

}



object NotANumber : SealedExpr()



// It exists in the testSealedDemo.kt file

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

  • Effective protection code
  • 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

This article has been collected on GitHub: Jetictors/KotlinLearn, welcome star articles continue to update, can be wechat search “J guy talk” first time read, everyone’s three-in-one is the best power for the old J, you are sure not to wave? If you have any mistakes or suggestions on this blog, please leave comments


Ah hello, five fingers mushroom niang ah, take a phone to scan!