Kotlin data class and sealed class
Data type
Kotlin can create a class that only contains data, the keyword is data
data class User(val name: String, val age: Int)
The compiler will automatically extract the following functions from the main constructor based on all declared attributes:
equals()
/hashCode()
toString()
Format like"User(name=John, age=42)"
componentN() functions
Correspond to attributes, arranged in order of declarationcopy()
function
If these functions have been clearly defined in the class or inherited from the super class, they will no longer be generated
In order to ensure the consistency and meaning of the generated code, the data class needs to meet the following conditions:
-
The main constructor contains at least one parameter.
-
All the parameters of the main constructor must be marked as
val
orvar
; -
Data class is not declared
abstract
,open
,sealed
orinner
; -
Data classes cannot inherit other classes (but can implement interfaces).
copy
To copy, use the copy() function, we can use this function to copy objects and modify some properties. For the User class above, the implementation will be similar to the following
fun copy(name: String = this.name, age: Int = this.age) = User(name, age)
Instance
Use the copy class to copy the User data class and modify the age attribute
data class User(val name: String, val age: Int)
fun main(args: Array<String>) {
val jack = User(name = "Jack", age = 1)
val olderJack = jack.copy(age = 2)
println(jack)
println(olderJack)
}
The output result is
User(name=Jack, age=1)
User(name=Jack, age=2)
Data class and deconstruction declaration
Component functions allow data classes to be used in destructuring declarations
val jane = User("Jane", 35)
val (name, age) = jane
println("$name, $age years of age") // prints "Jane, 35 years of age"
Standard data class
The standard library provides Pair and Triple. In most cases, naming the data class is a better design choice because the code is more readable and provides meaningful names and attributes
Sealed
Sealed classes are used to express restricted class inheritance structure: when a value is a limited number of types, but there can be no other types. In a sense, they are an extension of the enumeration class: the value set of the enumeration type is also limited, but there is only one instance of each enumeration constant, and a subclass of the sealed class can have more states that can contain Examples.
Declare a sealed class and use sealed to modify the class. The sealed class can have subclasses, but all subclasses must be embedded in the sealed class.
sealed cannot modify interface, abstract class (warning will be reported, but compilation errors will not occur)
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
fun eval(expr: Expr): Double = when (expr) {
is Const -> expr.number
is Sum -> eval(expr.e1) + eval(expr.e2)
NotANumber -> Double.NaN
}
The key advantage of using sealed classes is that when using when expressions, if you can verify that the statement covers all situations, you don't need to add an else clause to the statement.
fun eval(expr: Expr): Double = when(expr) {
is Expr.Const -> expr.number
is Expr.Sum -> eval(expr.e1) + eval(expr.e2)
Expr.NotANumber -> Double.NaN
// 不再需要 `else` 子句,因为我们已经覆盖了所有的情况
}