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