This is the 20th day of my participation in the November Gwen Challenge. Check out the details: The last Gwen Challenge 2021

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 class name {... }Copy the code

1.1.2 enumerate constants

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

Ex. :

/** * Example: Enumeration class about the result of a network request */ enum class State{/* NORMAL: NORMAL NO_DATA: data is empty NO_INTERNET: network connection is down ERROR: ERROR OTHER: NORMAL */ 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. attributeCopy the code

Through the above examples to illustrate:

// Use the infix symbol to access the enumeration constant state.normal.name state.no_data.name state.no_internet.name state.error.name state.other.nameCopy 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.
  • Enumeration variables are separated by commas (,). 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. :

fun main(args: Array<String>) { ConsoleColor.BLACK.print() } enum class ConsoleColor(var argb : Int fun print() {override fun print() {println(" I am the enumerator RED ")}}, WHITE(0xFFFFFF){override fun print() {println(" I'm WHITE ")}}, BLACK(0x000000){override fun print() {println(" BLACK ")}}, GREEN(0x00FF00){override fun print() {println(" I am the enumeration const GREEN ")}}; abstract fun print() }Copy the code

The output is:

I'm the enumeration constant BLACKCopy the code

1.4. Use of enumeration classes

  • Each enumeration constant contains two properties: name (enumeration constant name) and ordinal (enumeration constant position)
  • Values () and valueOf() methods are provided to detect whether the specified name matches any enumeration constant defined in an enumeration class.
  • Since Kotlin 1.1, you can use the enumValues() and enumValueOf() functions to access constants in an enumerated class in a generic manner.

1.4.1. Access enumeration variable properties

Ex. :

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() and enumValueOf()

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 Test with valueOf() and VALUES ()

Ex. :

println(Color.valueOf("RED"))
println(Color.values()[0])
println(Color.values()[1])
println(Color.values()[2])
println(Color.values()[3])
Copy the code

The output is:

RED
RED
WHITE
BLACK
GREEN
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, enumeration class source code analysis

  • namelyEnum.ktThis source file.

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.

1.5.1 companion Object {}

  • This is why we don’t need to instantiate an enumerated class to access enumerated constants.

1.5.2. Only two properties are provided

  • We used the above enumeration constant name (name) and enumeration constant position (ordinal) to attach the source code to these two properties:
/**
 * Returns the name of this enum constant, exactly as declared in its enum declaration.
 */
public final val name: String

/**
 * Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant
 * is assigned an ordinal of zero).
 */
public final val ordinal: Int
Copy the code

1.5.3. ImplementedComparableinterface

  • This is why we can get the location of the enumeration constant.

This is the Enum. Kt source file. Let’s see that it implements the Comparable interface

public abstract class Enum<E : Enum<E>>(name: String, ordinal: Int): Comparable<E>{
      ...
}
Copy the code

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

public interface Comparable<in T> { /** * Compares this object with the specified object for order. Returns zero if this  object is equal * to the specified [other] object, a negative number if it's less than [other], or a positive number * if it's greater than [other]. */ 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:

Interface Interface name {... }Copy the code

2.1.2, usage,

1. Keyword: colon (:), which is different from Java. 2. In Kotlin, the colon (:) is used in many places:

  • Used for the definition of variables
  • For inheritance
  • Used in the interface
  • Method return type declaration

Use format:

Class Class name: interface name {// Overridden interface functions, attributes, etc... }Copy the code

2.1.3. Examples

fun main(args: Var demo = Demo1() demo.fun1()} var demo = Demo1() demo.fun1()} Override fun fun1() {override fun fun1() {println(" I am fun1 in the interface ")}}Copy the code

The output is:

I'm the fun1 method in the interfaceCopy the code

2.2. Use of methods 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.

Ex. :

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 Fun5 ()} interface Demo2Interface{/** * define a method with no arguments and no return value */ fun1() /** * Define a method with arguments */ fun2(num: Funfun3 (num: Int) : Int/funfun4 () : funfun3 (num: Int) : Int String{return "fun4"} /** * defines a structless function, and the braces can be omitted */ fun5(){// If there is no expression in the function, the braces can be omitted. } class Demo2: Demo2Interface{override fun1() {println(" I am fun1() method ")} override fun2(num: Override fun fun3(num: Int) {println(" I am fun2() method, my argument is $num")} override fun fun3(num: Int): Int {println(" I am fun3() method, my argument is $num, and return a value of type Int ") return num + 3} Override fun fun4(): String {println(" I am the fun4() method and return a String value ") /* The fun4() method in the interface returns a "fun4" String by default. */ return super.fun4()} /* The fun5() interface has a structure, so it doesn't need to be overridden. Fun4 () the same * / / / override fun fun5 () {/ / super fun5 () / /}}Copy the code

The output is:

I'm a fun1() method, I'm a fun2() method, I take 5, I'm a fun3() method, I take 10, and I return a value of Int 13, I'm a fun4() method, and I return a value of String fun4Copy 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

Ex. :

Fun main(args: Array<String>) {var demo = Demo3(1,2) println(demo.sum())} interface Demo3Interface{val num1: Int val num2 : Int } class Demo3(override val num1: Int, override val num2: Int) : Demo3Interface{ fun sum() : Int{ return num1 + num2 } }Copy the code

The output is:

3
Copy the code

2.3.2 as accessor

Override manually and provide a get() method

Ex. :

fun main(args: Array<String>) {println(demo.result()) // You can change the value of the interface property demo.num4 = 10 println(demo.result())} interface Val num3: Int get() = 3 val num4: Int get() = 3 Int} class Demo3(override val num1: Int, override val num2: Int) : Demo3Interface{ Int get() = super.num3 override var num4: Int = 4 fun result() : Int{return num3 + num4}}Copy the code

The output is:

7 to 13Copy 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.

Ex. :

fun main(args: Array<String>) {// Class initialization val demo = Demo4() demo.fun1() demo.fun2()} interface Demo4InterfaceOne{fun fun1(){ Println (" I am fun1() in Demo4InterfaceOne ")} fun2(){println(" I am fun2() in Demo4InterfaceOne ")}} interface Demo4InterfaceTwo{fun fun1(){println(" I am fun1() in Demo4InterfaceTwo ")} fun fun2(){ Println (" I am fun2() in Demo4InterfaceTwo ")}} class Demo4: Demo4InterfaceOne,Demo4InterfaceTwo{ override fun fun1() { super<Demo4InterfaceOne>.fun1() super<Demo4InterfaceTwo>.fun1() } override fun fun2() { super<Demo4InterfaceOne>.fun2() super<Demo4InterfaceTwo>.fun2() }}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

I am personally engaged in Android development, before using Java language APP development because of the consideration of mobile phone performance problems almost no enumeration. Because enumerations consume too much memory. Of course, whether to use enumeration to facilitate the development of Android projects with Kotlin language to solve some problems, this is for xiaosheng to study. However, when developing server-side projects, enumerations are very convenient for some problems. For the interface class, it is the most important in a project, for the coupling and convenience of the code in the project can use the interface class to achieve a good project architecture, for the maintenance or reconstruction of the project, can have a good reflection. Many Java developers can relate