Enumeration classes

Enumeration class, a special class used to define a collection of constants. You can declare an enumerated class using enum class.

1.1 Creating enumeration Classes

Enumeration constants are separated by commas and each enumeration constant is an object

enum class Color{
    RED,
    BULE,
    YELLOW
}

fun main(a) {
    / / use
    println(Color.RED)
}
Copy the code

1.2 Obtaining Enumeration Information

val name: String // Get the enumeration name, the default name is the enumeration character name
val ordinal: Int // Gets the order in which enumerated values are defined in all enumerated arrays, starting at 0
Copy the code
fun main(a) {
    / / use
    val blue = Color.BULE
    println(blue.name)
    println(blue.ordinal)
}
Copy the code

1.3 Adding attributes to enumeration classes

Each enumeration is an instance of an enumeration class that can be initialized.

If you need to specify a value, you can use its constructor.

/ / 2.0 version
enum class Color2(val user: UserColor) {
    RED(UserColor("Little red".15)),
    BULE(UserColor("Little blue".20)),
    YELLOW(UserColor("Yellow".30));
}
data class UserColor(val name: String, val age: Int)
fun main(a) {
    / / 2.0 version
    println(Color2.BULE.user)
}
Copy the code

1.4 Defining functions

enum class Color2(val user: UserColor) {
    ...
    RED(UserColor("Little red".15));
    fun addUser(adduser:UserColor)=
        UserColor("${adduser.name}-${user.name}"
            ,adduser.age+user.age)

}

fun main(a) {
    // Enumeration defines functions
    println(Color2.RED.addUser(UserColor("New".40)))}Copy the code

1.5 Generic access to constants in enumerated classes

Since Kotlin 1.1, constants in enumerated classes can be accessed generically using the enumValues

() and enumValueOf

() functions

@SinceKotlin("1.1")
public inline fun <reified T : Enum<T>> enumValues(a): Array<T>

/** * Returns an enum entry with specified name. */
@SinceKotlin("1.1")
public inline fun <reified T : Enum<T>> enumValueOf(name: String): T
/ / use
fun main(a) {
    println(enumValueOf<Color>("RED"))
    println(enumValues<Color2>().joinToString { it.user.toString() })
}
Copy the code

1.6 Algebraic Data Types (ADT)

An enumerated class is a simple ADT that can be used to represent a closed set of subtypes.

The key benefit of using enumerations is that when you use a WHEN expression, you don’t need to add an else clause to the statement if you can verify that the statement covers all cases.

enum class ColorADT {
    RED,
    BULE,
    YELLOW
}

class TakeColor(var colorADT: ColorADT) {
    fun selectColor(a): String {
        return when (colorADT) {
            ColorADT.RED -> "Red"
            ColorADT.BULE -> "Blue"
            ColorADT.YELLOW -> "Yellow"
             // The 'else' clause is no longer needed because we have covered all cases}}}fun main(a) {
    println(TakeColor(ColorADT.BULE).selectColor())
}
Copy the code

But if we want to give a hint when the return is red. If you use enumerated classes, then the need to determine is a little more complicated. For more complex ADTS, you can use Kotlin’s Sealed Class for more complex definitions.

2, Sealed Class

  • For more complex ADTs, you can use Kotlin’s Sealed Class for more complex definitions. The sealed class can be used to define an ADT that is similar to an enumeration class, but you have more flexibility to control a subtype.

  • A sealed class can have several subclasses. To inherit a sealed class, these subclasses must be defined in the same file as it.

  • Sealed keyword cannot modify interface,abstract class(will report warning, but will not compile errors)

2.1 Creating a Containment Class

sealed class ColorSealed{
    // The following are subclasses of the containment class
    // Using object is a singleton, because the following two subclasses have no attributes, no matter how many times they are generated
    object Blue : ColorSealed()
    object Yellow : ColorSealed()
    // This subclass has attributes, maybe different attributes, so different objects are generated
    class Red(val toast:String) : ColorSealed()
}
Copy the code

2.2 the use of

The key benefit of using a sealed class is that when you use a WHEN expression, you don’t need to add an else clause to the statement if you can verify that the statement covers all cases.

class TakeColorSealed(var colorSealed: ColorSealed) {
    fun selectColor(a): String {
        return when (colorSealed) {
            is ColorSealed.Blue -> "Blue"
            is ColorSealed.Yellow -> "Yellow"
            is ColorSealed.Red ->
                "Red,${(this.colorSealed as ColorSealed.Red).toast}"
            // The else clause is no longer needed because we have covered all cases}}}fun main(a) {
    println(TakeColorSealed(ColorSealed.Blue).selectColor())
    println("-- -- -- -- -- -- -- -- -- --")
    println(TakeColorSealed(ColorSealed.Red("Warning warning!!")).selectColor())
}
Copy the code

This is different from the use of enumerated classes. The is keyword is used.

Convert the current ColorSealed to ColorSealed.Red when calling the Red prompt, because compile time does not know whether you passed Red or something else.

Third, data

Use the data class keyword to create a class that contains only data, also called a data class. This is unique to Kotlin, Java has no data classes.

The compiler automatically extracts the following functions from the main constructor based on all declared attributes:

  • Generate equals() and hasCode()

  • Generates the toString() function from the class name (argument 1 = value 1, argument 2 = value 2,… .). Constitute a

  • Component1 (), Component2 (),… The componentN() function, which corresponds to the declaration order of attributes.

  • The copy () function

The data class must meet the following conditions:

  • The main constructor takes at least one argument.

  • All primary constructors must have arguments identified as val or var.

  • Data classes cannot be declared abstract,open,sealed, or inner.

  • Data classes cannot inherit from other classes (but can implement interfaces).

data class DaTang (var name:String ,val age:Int)
Copy the code

In the absence of a structure, the curly braces {} may be omitted.

3.1 Creating Data Classes

data class DaTang (var name:String ,val age:Int) {val emperor = "$name, is after the Sui Dynasty unified the Central Plains dynasty, a total of 21 emperors, enjoy the country -$age- years."
}

fun main(a) {
    println(DaTang("Tang dynasty".289))}Copy the code

Instead of using the data class keyword, use the class keyword as follows:

3.2 Personalization implementation of toString, Equals, and hashCode

3.3 = = symbol

data class DaTang (var name:String ,val age:Int) {val emperor = "$name, is after the Sui Dynasty unified the Central Plains dynasty, a total of 21 emperors, enjoy the country -$age- years."
}
class DaTang2 (var name:String ,val age:Int) {val emperor = "$name, is after the Sui Dynasty unified the Central Plains dynasty, a total of 21 emperors, enjoy the country -$age- years."
}
fun main(a) {
    println(DaTang("Tang dynasty".289))
    // "== "compares content equals(Any).
    // The equals function of Any is not overridden. The equals function of Any is used by default.
    // "===" compares references (class size)
    println(DaTang2("Tang dynasty".289) == DaTang2("Tang dynasty".289))

    // Use data class to override equals.
    println(DaTang("Tang dynasty".289) == DaTang("Tang dynasty".289))}Copy the code

3.4 the copy () function

The copy() function should be similar to the Clone () method in Java

data class DaTang (var name:String ,val age:Int) {val emperor = "$name, is after the Sui Dynasty unified the Central Plains dynasty, a total of 21 emperors, enjoy the country -$age- years."
}
fun main(a) {
    val datang = DaTang("Tang dynasty".289)
    println(datang)//DaTang(name= tang, age=289)
    // create a new object
    val diguo = datang.copy(age=500)
    println(diguo)//DaTang(name= tang, age=500)

}
Copy the code

3.5 Deconstructing The Statement

Data class: automatically generated component1(), Component2 (),… The componentN() function, which corresponds to the declaration order of attributes.

Common class: Define component1(), Component2 (),… ComponentN ()

data class DataDaSong(var name:String ,var age:Int)
class DaSong(var name:String ,var age:Int) {// Destruct syntax: you must start at Component1
    operator fun component1(a) = name
    operator fun component2(a) = age
}

fun main(a) {
    Component1, Component2... componentN
    var (name,age) = DaSong("Northern song dynasty".167)
    println("$nameAfter the five dynasties and ten Kingdoms in Chinese history, there were nine emperors who enjoyed the kingdom$age- the years")
    // Generate Operator Fun Component1 automatically using data classes to support destruct syntax
    var (dataname,dataage) = DataDaSong("Northern song dynasty".167)
    println("Data class:$datanameAfter the five dynasties and ten Kingdoms in Chinese history, there were nine emperors who enjoyed the kingdom$dataage- the years")}Copy the code

Look at the data class decompilation code:

4. Extend

Kotlin allows a class to inherit from another class

All classes in Kotlin inherit from the Any class

The Any class is the superclass of all classes, and the default superclass for classes that do not have a supertype declaration

Kotlin classes are closed by default, and to make a class open for inheritance, you must decorate it with the open keyword.

Note:

In Kotlin, the Any class is the superclass of all classes

In Java, the Object class is the superclass of all classes

4.1 Any superclasses

Any provides three functions by default:

public open class Any {
    
    public open operator fun equals(other: Any?).: Boolean

    public open fun hashCode(a): Int

    public open fun toString(a): String
}

Copy the code

You can see from this that both classes and functions use the open keyword modifier.

It is also found that the function is defined but not implemented. Why is that? Because Kotlin is a cross-platform language that runs on Android, macOS, Windows, and JavaScript, there are different implementations for different platforms to support cross-platform friendliness, so it is not shown here.

4.2 a derived class

/* Food base */
open class Food{
    fun explain(a) = "Food explain"
}

class Apple :Food(){
    
}
Copy the code

Do not add the open keyword to prevent inheritance drops, as shown below:

4.3 Function Rewriting

When you declare a function with fun ina base class, the function defaults to final and cannot be overridden by subclasses.

If subclasses are allowed to override the function, then it must be decorated with the open keyword, and subclass overrides use the override keyword.

/* Food base */
open class Food{
    // Functions must be decorated with the open keyword to be overridden by subclasses
    open fun explain(a) = "Food explain"
}
/* Inherits Food */
class Apple :Food() {// Override the parent function with the override keyword
    override fun explain(a) = "Apple explain "
}
Copy the code

Override is a keyword rather than an annotation in Kotlin.

use

fun main(a) {
    // Polymorphic: an object of a superclass type that references a subclass type
    val f: Food = Apple()
    println(f.explain())
}
Copy the code

4.4 Attribute Rewriting

/* Food base */
open class Food {
    open val price = 100. }/* Inherits Food */
class Apple : Food() {
    override var price = 36. }fun main(a) {
    // Polymorphic: an object of a superclass type that references a subclass type
    val f: Food = Apple()
    println(f.explain())//Apple explain 36
}
Copy the code

4.5 Type Detection (is)

Kotlin’s IS operator can be used to check the type of an object.

    println(f is Food)//true
    println(f is Apple)//true
    println(f is File)//false
Copy the code

Intelligent type conversion (as)

Kotlin’s AS operator can be used to type an object.

Intelligent security conversion operator: as?

as? Safely convert to a type. If the conversion is not possible, null is returned instead of throwing a ClassCastException.

Let’s modify it based on the above example.

    var asTest :String? = ""
    // Unsafe conversion operator as
// println(asTest as Int)//ClassCastException
    // The safe conversion operator as?
    println(asTest as? Int)//null
Copy the code