Looking and searching, courty,’t — li qingzhao “sound slow”

In the previous section, the detailed class (class) did an example explanation, mentioned the class (class) instantiation, constructor, declaration, implementation, and Java class differences. But the use of Kotlin’s classes goes far beyond that. This article discusses the use of Enum and Interface classes in Kotlin in detail.

directory

Enumeration classes

1.1. Declaration and enumeration constants

  • Key words:enum
  • Enumerated constants: Objects under an enumerated class, each containing zero to more enumerated constants.

1.1.1, statements

The enum keyword precedes the class keyword in the class header

Declaration format:

enum classThe name of the class {

.

}

Copy the code

1.1.2 enumerate constants

Each enumerated constant in an enumerated class is an object, and they are separated by commas.

Example: Enumeration class about the result of a network request

enum class State{



    / *

NORMAL: NORMAL

NO_DATA: data is empty

NO_INTERNET: The network is disconnected

ERROR: ERROR

OTHER: OTHER

* /


    NORMAL,NO_DATA,NO_INTERNET,ERROR,OTHER

}

Copy the code

1.1.3. Access enumeration constants

You don’t need to instantiate an enumeration class to access enumeration constants

Use mode:

Enumerates class names. Enumerates constants. attribute

Copy the code

Through the above examples to illustrate:

// Use infix symbols to access enumeration constants

State.NORMAL.name

State.NO_DATA.name

State.NO_INTERNET.name

State.ERROR.name

State.OTHER.name

Copy the code

This is just to show you how to access an enumerated constant. The use of enumerated constants is not covered. Please be patient with the use of enumeration constants. Details on how to use it are described below.

1.2. Initialization of enumeration constants

  • Because each enumeration is an instance of an enumeration class, they can be initialized.

Ex. :

enum class Color(var argb : Int) {

    RED(0xFF0000),

    WHITE(0xFFFFFF),

    BLACK(0x000000),

    GREEN(0x00FF00)

}

Copy the code

1.3. Enumerate anonymous classes for constants

  • To implement an anonymous class that enumerates constants, you must provide an abstract method (a method that must be overridden). And the method is defined inside the enumeration class. And it must come after the enumeration variable.
  • Use commas between enumeration variables (.) split. But the last enumeration variable must be terminated with a semicolon. Otherwise you can’t define an abstract method.
  • As stated above, each enumerated constant is an object.

Ex. :

enum class ConsoleColor(var argb : Int) {

    RED(0xFF0000) {

        override fun print(a) {

            println("I'm the enumeration constant RED.")

        }

    },

    WHITE(0xFFFFFF) {

        override fun print(a) {

            println("I'm the enumeration constant WHITE")

        }

    },

    BLACK(0x000000) {

        override fun print(a) {

            println("I'm the enumeration constant BLACK.")

        }

   },

    GREEN(0x00FF00) {

        override fun print(a) {

            println("I'm the enumeration constant GREEN.")

        }

    };



    abstract fun print(a)

}



fun main(args: Array<String>) {

    ConsoleColor.BLACK.print()

}

Copy the code

The output is:

I'm the enumeration constant BLACK

Copy the code

1.4. Use of enumeration classes

  • Each enumeration constant contains two properties:Name (enumeration constant name)andOrdinal (enumeration constant position)
  • providesvalues()andvalueOf()Method to check whether the specified name matches any enumeration constants defined in an enumeration class.
  • Since theKotlin 1.1Up, ready to useenumValues()andenumValueOf()The function accesses constants in an enumerated class in a generic way.

1.4.1. Access enumeration variable properties

fun main(args: Array<String>) {

    println("name = " + Color.RED.name + "\tordinal = " + Color.RED.ordinal)

    println("name = " + Color.WHITE.name + "\tordinal = " + Color.WHITE.ordinal)

    println("name = " + Color.BLACK.name + "\tordinal = " + Color.BLACK.ordinal)

    println("name = " + Color.GREEN.name + "\tordinal = " + Color.GREEN.ordinal)

}



enum class Color(var argb : Int) {

     RED(0xFF0000),

     WHITE(0xFFFFFF),

     BLACK(0x000000),

     GREEN(0x00FF00)

}   

Copy the code

The output is:

name = RED    ordinal = 0

name = WHITE    ordinal = 1

name = BLACK    ordinal = 2

name = GREEN    ordinal = 3

Copy the code

1.4.2, use,enumValues<T>()andenumValueOf<T>()access

Example: The enumeration class is still the Color class in the above example

println(enumValues<Color>().joinToString { it.name })

println(enumValueOf<Color>("RED"))

Copy the code

The output is:

RED, WHITE, BLACK, GREEN

RED

Copy the code

1.4.3, use,valueOf()andvalues()detection

    println(Color.valueOf("RED"))

    println(Color.values(a)[1])

    println(Color.values(a)[2])

Copy the code

The output is:

RED

WHITE

BLACK

Copy the code

Where color.valueof (” Non-existent enumeration constant “) is used, IllegalArgumentException is thrown, that is, the enumeration variable does not exist. Using color.values ()[greater than enumeration constant position] throws an out-of-bounds subscript exception.

1.5. Source code analysis

The source file Enum. Kt. Here I outline the methods, properties, and so on of the source file. If you’re interested, check out the source file. There’s not much in it.

This is the Enum. Kt source file.

public abstract class Enum<E : Enum<E>>(name: String, ordinal: Int): Comparable<E>{

    companion object {}



    public final val name: String



    public final val ordinal: Int



    public override final fun compareTo(other: E)Int



    protected final fun clone(a): Any



    public override final fun equals(other: Any?).Boolean



    public override final fun hashCode(a)Int



    public override fun toString(a): String

}

Copy the code

Companion Object {} is implemented by default, which is why you don’t need to instantiate an enumerated class to access enumerated constants

Only two properties are provided, namely the enumeration constant name (name) and enumeration constant position (ordinal) we used above

The Comparable interface is implemented, which is why we can get the position of the enumeration constant

Let’s see what’s going on in Comparable. Kt. In fact, it provides a sort function…

public interface Comparable<in T{

    // For reasons of length, the comments are omitted

    public operator fun compareTo(other: T)Int

}

Copy the code

So much for enumeration classes. If you are not sure, you can read more articles, or look at the source code, official documentation, etc. Of course, it would be nice to follow my example and type through the code yourself.

2. Interface classes

2.1 basic use of interfaces

2.1.1, statements

Key word: interface

Definition format:

interfaceThe interface name{

.

}

Copy the code

2.1.2, usage,

  • Use colon (:), this point is andJavaDifferent.JavaThe interface used in theimplementsThe keyword
  • inKotlinIn the colon (:) for variable definitions, for inheritance, for interfaces, return type declarations for methods

Use format:

classClass name: interface name {

    // Overridden interface functions, attributes, etc

.

}

Copy the code

2.1.3. Examples

/ * *

* I defined the interface

* /


interface Demo1Interface{



    // Define the method

    fun fun1(a)

}



/ * *

* The implementation class of the interface

* /


class Demo1 : Demo1Interface{

    override fun fun1(a) {

        println("I'm the fun1 method in the interface.")

    }

}



fun main(args: Array<String>) {



   // Class initialization

   var demo = Demo1()



   demo.fun1()

}

Copy the code

The output is:

I'm the fun1 method in the interface

Copy the code

2.2. Use of functions in interfaces

  • A function without a structure can omit the braces and be called without forcing the function with a structure to be overridden. It doesn’t matter if you don’t understand, the following code has comments.
interface Demo2Interface{



    / * *

* Defines a method with no arguments and no return value

* /


    fun fun1(a)



    / * *

* Define a method with parameters

* /


    fun fun2(num: Int)



    / * *

* Define a method that takes parameters and returns values

* /


    fun fun3(num: Int) : Int



    // The following two methods have structures, so they can not be overridden



    / * *

* Defines a method with no arguments and a return value

* /


    fun fun4(a) : String{

        return "fun4"

    }



    / * *

* Defines a structless function. The curly braces can be omitted

* /


    fun fun5(a){

        // If no expression exists in the function, the curly braces can be omitted.

        // Like fun1

    }

}



class Demo2 : Demo2Interface{



    override fun fun1(a) {

        println("I'm the fun1() method")

    }



    override fun fun2(num: Int) {

        println("I'm the fun2() method, and my argument is$num")

    }



    override fun fun3(num: Int)Int {

        println("I'm the fun3() method, and my argument is$numAnd return a value of type Int.")

        return num + 3

    }



    override fun fun4(a): String {

        println("I'm a fun4() method and I return a String value.")



        / *

The fun4() method in the interface returns the "fun4" string by default.

You can return the default with super.fun4()

You can also omit the super keyword and return a string yourself

* /


        return super.fun4()

    }



    / *

Fun5 () in the interface has a structure so it doesn't need to be overridden,

Fun4 () the same

* /




    // override fun fun5() {

    // super.fun5()

    / /}

}



fun main(args: Array<String>) {

    var demo = Demo2()



    demo.fun1()

    demo.fun2(5)

    println(demo.fun3(10))

    println(demo.fun4())



    // Can be called directly without overwriting the method

    demo.fun5()

}

Copy the code

The output is:

I'm the fun1() method

I'm the fun2() method, and my argument is5

I'm the fun3() method, and my argument is10And return oneIntThe value of the type

13

I am the fun4() method and return oneStringThe value of the type

fun4

Copy the code

2.3. Use of attributes in interfaces

  • Declare attributes in the interface. Properties in an interface are either abstract or provide an implementation of the accessor. Interface attributes cannot have backup fields. And accessors cannot refer to them.

2.3.1 as an abstraction

  • That is, the property is overridden in the class parameters of the implementation class. This is also an implementation that is overridden with code hints
interface Demo3Interface{



    val num1: Int



    val num2 : Int  

}



class Demo3(override val num1: Int.override val num2: Int) : Demo3Interface{

    fun sum(a) : Int{

        return num1 + num2

    }

}



fun main(args: Array<String>) {

    var demo = Demo3(1.2)

    println(demo.sum())

}

Copy the code

The output is:

3

Copy the code

2.3.2 as accessor

Override manually and provide a get() method

interface Demo3Interface{



     // Declare variables and provide default values

     Val num3: Int = 3

    val num3: Int

    get() = 3



    val num4: Int

}



class Demo3(override val num1: Int.override val num2: Int) : Demo3Interface{



    // Provide accessor implementation

    override val num3: Int

        get() = super.num3



    // Manual assignment

    override var num4: Int = 4



    fun result(a) : Int{

        return num3 + num4

    }

}



fun main(args: Array<String>) {

    println(demo.result())



    // You can also change the value of the interface property here

    demo.num4 = 10

    println(demo.result())

}

Copy the code

The output is:

7

13

Copy the code

2.4 Solve the interface conflict problem

  • The problem is that when we declare many types in a parent class, it is possible to have multiple implementations of a method.
interface Demo4InterfaceOne{

    fun fun1(a){

        println("I'm fun1() in Demo4InterfaceOne.")

    }



    fun fun2(a){

        println("I'm fun2() in Demo4InterfaceOne.")

    }

}



interface Demo4InterfaceTwo{

    fun fun1(a){

        println("I'm fun1() in Demo4InterfaceTwo.")

    }



    fun fun2(a){

        println("I'm fun2() in Demo4InterfaceTwo.")

    }

}



class Demo4 : Demo4InterfaceOne.Demo4InterfaceTwo{



    override fun fun1(a) {

        super<Demo4InterfaceOne>.fun1()

        super<Demo4InterfaceTwo>.fun1()

    }



    override fun fun2(a) {

        super<Demo4InterfaceOne>.fun2()

        super<Demo4InterfaceTwo>.fun2()

    }



}



fun main(args: Array<String>) {



    // Class initialization

    val demo = Demo4()



    demo.fun1()

    demo.fun2()

}

Copy the code

The output is:

I'm fun1() in Demo4InterfaceOne

I'm fun1() in Demo4InterfaceTwo

I'm fun2() in Demo4InterfaceOne

I'm fun2() in Demo4InterfaceTwo

Copy the code

Demo4 implements Demo4InterfaceOne and Demo4InterfaceTwo interfaces, and there are two methods with the same method name in both interfaces. So the compiler doesn’t know which one to choose, so we use super< interface name >. Method name to distinguish.

Third, summary

For enumeration and interface, it is the most important in a project, for the coupling of the code in the project, the convenience of interface class can be used to achieve a good project architecture, for the maintenance or reconstruction of the project, can have a good embodiment. Many Java developers can relate

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!