目录
1. Data Classes数据类
(1) copy()函数
(2) 数据类的解构
(3) 标准数据类 Pair 和 Triple
2. Sealed Classes密封类
3. Nested Classes嵌套类
4. Enum 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()等方法中
可以使用copy()函数来复制一个数据类中的部分值,保持其他属性值不变
val jack = User(name = "Jack", age = 1)
val olderJack = jack.copy(age = 2)
解构相当于Compotent函数的逆向映射:
val jane = User("Jane", 35)
val (name, age) = jane
println("$name, $age years of age") // prints "Jane, 35 years of age"
Pair是二元组数据类,Triple是三元组数据类,都有一个toList的扩展函数
密封类使用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) {
val const = eval(Const(1.1))
val sum = eval(Sum(Const(1.2), Const(0.8)))
println(const)
println(sum)
}
嵌套类即在一个类内部嵌套定义另一个类,可以多层嵌套,在调用时使用"类名."的方式,
普通的嵌套类没有持有外部类的引用,因此无法调用外部类的成员。
使用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详见下一章
枚举类的主要使用目的是实现类型安全的枚举
enum class Direction {
NORTH, SOUTH, WEST, EAST
}
由于每个枚举值都是一个对象,所以可以如下来初始化枚举类的值:
enum class Color(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}
fun main(args: Array) {
val red = Color.RED
println(red.rgb)
}
枚举常量可以声明自己的匿名类,枚举类内的枚举值和其他成员直接用“;”隔开
枚举类也可以定义嵌套类和内部类,枚举类只能实现接口,不能继承一个类
import java.util.function.BinaryOperator
import java.util.function.IntBinaryOperator
enum class IntArithmetics : BinaryOperator, 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) {
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
println(enumValues().joinToString { "${it.name} ---- ${it.ordinal}" })
println(enumValueOf("RED").rgb)