一、枚举类
枚举类,用来定义常量集合的一种特殊类。使用 enum class 可以声明一个枚举类。
1.1 创建枚举类
枚举常量用逗号分隔,每个枚举常量都是一个对象
enum class Color{ RED, BULE, YELLOW } fun main() { //使用 println(Color.RED) }
1.2 获取枚举相关信息
val name: String //获取枚举名称,,默认名称为枚举字符名 val ordinal: Int //获取枚举值在所有枚举数组中定义的顺序,值从 0 开始
fun main() { //使用 val blue = Color.BULE println(blue.name) println(blue.ordinal) }
1.3 枚举类添加属性
每一个枚举都是枚举类的实例,它们可以被初始化。
若需要指定值,则可以使用其构造函数。
//2.0版本 enum class Color2(val user: UserColor) { RED(UserColor("小红", 15)), BULE(UserColor("小蓝", 20)), YELLOW(UserColor("小黄", 30)); } data class UserColor(val name: String, val age: Int) fun main() { //2.0版本 println(Color2.BULE.user) }
1.4 定义函数
enum class Color2(val user: UserColor) { ... RED(UserColor("小红", 15)); fun addUser(adduser:UserColor)= UserColor("${adduser.name}-${user.name}" ,adduser.age+user.age) } fun main() { //枚举定义函数 println(Color2.RED.addUser(UserColor("新", 40))) }
1.5 以泛型的方式访问枚举类中的常量
自 Kotlin 1.1 起,可以使用 enumValues()
和enumValueOf()
函数以泛型的方式访问枚举类中的常量
@SinceKotlin("1.1") public inline fun <reified T : Enum<T>> enumValues(): Array<T> /** * Returns an enum entry with specified name. */ @SinceKotlin("1.1") public inline fun <reified T : Enum<T>> enumValueOf(name: String): T //使用 fun main() { println(enumValueOf<Color>("RED")) println(enumValues<Color2>().joinToString { it.user.toString() }) }
1.6 代数数据类型(ADT)
可以用来表示一组子类型的闭集,枚举类就是一种简单的ADT。
使用枚举的关键好处在于使用 when 表达式的时候,如果能够 验证语句覆盖了所有情况,就不需要为该语句再添加一个 else 子句了。
enum class ColorADT { RED, BULE, YELLOW } class TakeColor(var colorADT: ColorADT) { fun selectColor(): String { return when (colorADT) { ColorADT.RED -> "红色" ColorADT.BULE -> "蓝色" ColorADT.YELLOW -> "黄色" // 不再需要 `else` 子句,因为我们已经覆盖了所有的情况 } } } fun main() { println(TakeColor(ColorADT.BULE).selectColor()) }
但是如果我们想在返回是红色的时候给一个提示。如果使用枚举类,那么还需要判断就有一些复杂了。对于更复杂的ADT,你可以使用Kotlin的密封类(sealed class)来实现更复杂的定义。
二、密封类(sealed class)
- 对于更复杂的ADT,你可以使用Kotlin的密封类(sealed class)来实现更复杂的定义,密封类可以用来定义一个类似于枚举类的ADT,但你可以更灵活地控制某个子类型。
- 密封类可以有若干个子类,要继承密封类,这些子类必须和它定义在同一个文件里。
- sealed 关键字不能修饰 interface ,abstract class(会报 warning,但是不会出现编译错误)
2.1 创建密封类
sealed class ColorSealed{ //以下都是密封类的子类 //使用object用的是单例,因为下面两个子类没有属性,不管生成多少次都一样 object Blue : ColorSealed() object Yellow : ColorSealed() //这个子类有属性,可能属性不同,所以要生成不同的对象 class Red(val toast:String) : ColorSealed() }
2.2 使用
使用密封类的关键好处在于使用 when 表达式的时候,如果能够 验证语句覆盖了所有情况,就不需要为该语句再添加一个 else 子句了。
1.class TakeColorSealed(var colorSealed: ColorSealed) { fun selectColor(): String { return when (colorSealed) { is ColorSealed.Blue -> "蓝色" is ColorSealed.Yellow -> "黄色" is ColorSealed.Red -> "红色,${(this.colorSealed as ColorSealed.Red).toast}" //不再需要 else 子句,因为我们已经覆盖了所有的情况 } } } fun main() { println(TakeColorSealed(ColorSealed.Blue).selectColor()) println("----------") println(TakeColorSealed(ColorSealed.Red("警告警告!!!")).selectColor()) }
这里跟枚举类的使用不太一样。用到了 is 关键字。
调用红色提示的时候将当前的ColorSealed转换为ColorSealed.Red,因为编译时也不知道你传入的是Red还是其他的。