Kotlin笔记5-Data Classes数据类、Sealed Classes密封类、Nested Classes嵌套类、Enum Classes枚举类

目录

1. Data Classes数据类

(1) copy()函数

(2) 数据类的解构

(3) 标准数据类 Pair 和 Triple

2. Sealed Classes密封类

3. Nested Classes嵌套类

4. Enum Classes枚举类


1. Data Classes数据类

数据类的作用主要就是用来存储数据。在class类名前用data修饰符

data class User(val name: String, val age: Int)

这样编译器自动生成equals()/hashCode()、toString()、componentN() functions、copy(),

定义数据类的要求:

(1)主构造函数至少要有一个参数

(2)主构造函数的所有参数需要标记为val或者var,可以有次级构造函数

(3)数据类不能是abstract、open、sealed、inner,只能是final

(4)数据类可以实现interface或者继承其他类

如果想有一个无参的构造函数,可以在主构造函数里给所有参数赋默认值

data class User(val name: String = "", val age: Int = 0)

val user = User()
user.name
user.age

⚠️注意:数据类中自动生成的方法,只对主构造函数中的参数有效,在数据类结构中生成的成员变量,并不在默认生成的equals()/hashCode()、toString()等方法中

(1) copy()函数

可以使用copy()函数来复制一个数据类中的部分值,保持其他属性值不变

val jack = User(name = "Jack", age = 1)
val olderJack = jack.copy(age = 2)

(2) 数据类的解构

解构相当于Compotent函数的逆向映射:

val jane = User("Jane", 35) 
val (name, age) = jane
println("$name, $age years of age") // prints "Jane, 35 years of age"

(3) 标准数据类 Pair 和 Triple

Pair是二元组数据类,Triple是三元组数据类,都有一个toList的扩展函数

2. Sealed Classes密封类

密封类使用sealed修饰,目的是为了限制类的继承结构,即将一个值限制在有限的集合中,类似于枚举类,只是每个枚举常量只存在一个实例,而密封类的一个子类可以有包含状态的多个实例。

密封类的子类必须在当前一个文件中,其子类则没有此限制。密封类自身是abstract抽象的,可以有抽象的成员,不能直接被实例化

Sealed classes不允许有非private的构造函数,默认构造函数都是private

使用Sealed classes的主要场景是在使用when表达式的时候,如果能够验证语句覆盖了所有的情况,那么可以不用再添加else子句

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 `else` clause is not required because we've covered all the cases
}

fun main(args: Array<String>) {
    val const = eval(Const(1.1))
    val sum = eval(Sum(Const(1.2), Const(0.8)))
    println(const)
    println(sum)
}

3. Nested Classes嵌套类

嵌套类即在一个类内部嵌套定义另一个类,可以多层嵌套,在调用时使用"类名."的方式,

普通的嵌套类没有持有外部类的引用,因此无法调用外部类的成员。

使用inner修饰后,变成嵌套的内部类,这时可以调用外部类的成员。

class Outer {
    private val bar: Int = 1
    class Nested {
        fun foo() = 2
    }
}
val demo = Outer.Nested().foo() // == 2


class Outer {
    private val bar: Int = 1
    inner class Inner {
        fun foo() = bar
    }
}
val demo = Outer().Inner().foo() // == 1

kotlin中使用object expression对象表达式的形式来构造匿名内部类对象

关于object expression详见下一章

4. Enum Classes枚举类

枚举类的主要使用目的是实现类型安全的枚举

enum class Direction {
    NORTH, SOUTH, WEST, EAST
}

由于每个枚举值都是一个对象,所以可以如下来初始化枚举类的值:

enum class Color(val rgb: Int) {
    RED(0xFF0000),
    GREEN(0x00FF00),
    BLUE(0x0000FF)
}

fun main(args: Array<String>) {
    val red = Color.RED
    println(red.rgb)
}

枚举常量可以声明自己的匿名类,枚举类内的枚举值和其他成员直接用“;”隔开

枚举类也可以定义嵌套类和内部类,枚举类只能实现接口,不能继承一个类

import java.util.function.BinaryOperator
import java.util.function.IntBinaryOperator

enum class IntArithmetics : BinaryOperator<Int>, IntBinaryOperator {
    PLUS {
        override fun apply(t: Int, u: Int): Int = t + u
    },
    TIMES {
        override fun apply(t: Int, u: Int): Int = t * u
    };

    override fun applyAsInt(t: Int, u: Int) = apply(t, u)
}

fun main(args: Array<String>) {
    val a = 13
    val b = 31
    for (f in IntArithmetics.values()) {
        println("$f($a, $b) = ${f.apply(a, b)}")
    }
}

可以使用如下方法,根据枚举的名称或者枚举值,或者取得枚举类的所有枚举值集合,或者遍历它

EnumClass.valueOf(value: String): EnumClass
EnumClass.values(): Array<EnumClass>

println(enumValues<Color>().joinToString { "${it.name} ---- ${it.ordinal}" })
println(enumValueOf<Color>("RED").rgb)

猜你喜欢

转载自blog.csdn.net/unicorn97/article/details/81407495