----《第一季Kotlin崛起:次世代Android开发 》学习笔记
总目录:每天学一点 Kotlin ---- 目录
上一篇:每天学一点 Kotlin -- 多彩的类:嵌套类
下一篇:每天学一点 Kotlin -- 多彩的类:对象表达式
1. 枚举类
1.1 枚举类和数据类有点相似。将相关的常量分组到同一个枚举类型里,并且每个常量都是该枚举类的实例。什么是实例呢,就是通过它可以直接访问类里面的属性或调用类里面的方法。
1.2 举个栗子
1.2.1 不使用枚举类的场景:
class PuTongClass {
var num: Int = 5
val name = "puTongClass"
fun getNum() {
println("获取类里面的属性:$num")
println("只能通过定义类的实例对象,才能调用类的方法")
}
}
fun test1() {
val puTongClass = PuTongClass()
puTongClass.getNum()
println("puTongClass.name = ${puTongClass.name}")
}
fun main(args: Array<String>) {
test1()
}
打印结果:
获取类里面的属性:5
只能通过定义类的实例对象,才能调用类的方法
puTongClass.name = puTongClass
1.2.2 使用枚举类的场景:
enum class EnumClass {
weekday1, weekday2, weekday3;
fun printWeekday(): Unit {
println("枚举类的常量(成员变量)可以直接调用类里的方法")
}
}
fun test2() {
EnumClass.weekday3.printWeekday()
// var weekday2 = EnumClass() // 虽然是类,但是不能创建对象
}
fun main(args: Array<String>) {
test2()
}
打印结果:
枚举类的常量(成员变量)可以直接调用类里的方法
1.3 通过上面代码可知:
(1) 枚举类的声明必须用关键字 enum 标记
(2) 每个枚举常量都是一个枚举类型的实例对象,多个常量之间用逗号隔开
(3) 最后一个枚举常量定义完成后,需要加分号结束 --- 在 Kotlin 中为数不多需要加分号的地方
2. 初始化
2.1 因为枚举的每个常量都是枚举类的实例,所有枚举类的初始化在声明常量的时候就能直接进行。
2.2 举个栗子:
2.2.1 普通类的初始化:
class Famililer(var rank: Int) {}
fun test3() {
var father = Famililer(1)
var mother = Famililer(2)
var son = Famililer(3)
var daugther = Famililer(4)
println("排行:父亲:${father.rank}, 母亲:${mother.rank}, 儿子:${son.rank}, 女儿:${daugther.rank}")
}
fun main(args: Array<String>) {
test3()
}
打印结果:
排行:父亲:1, 母亲:2, 儿子:3, 女儿:4
2.2.2 枚举类的初始化:
enum class Familier2(var rank: Int) {
father(1), mother(2), son(3), daugther(4)
}
fun test4() {
println(
"使用枚举类 -- 排行:父亲:${Familier2.father.rank}, 母亲:${Familier2.mother.rank}, 儿子:${Familier2.son.rank}" +
", 女儿:${Familier2.daugther.rank}"
)
}
fun main(args: Array<String>) {
test4()
}
打印结果:
使用枚举类 -- 排行:父亲:1, 母亲:2, 儿子:3, 女儿:4
可以看出:枚举类包含一个主构造函数,作用也是声明一个属性 rank。在声明枚举常量的时候直接初始化,这样初始化语句就是简单的一句代码,相比于普通类的初始化简洁了很多。
3. 枚举类的其他优点
3.1 枚举类是优点不止是初始化简洁,它自带的很多方法也是很强大的:
(1) compareTo() 和 ordinal(): 这两个方法都和枚举常量的顺序相关。compareTo() 方法比较两个枚举常量的顺序,前者先于后者则返回 Int 类型的-1,前者后于后者则返回1,两者相等则返回0。ordinal() 方法则是返回枚举常量的序数,也就是它在枚举声明中的位置,其中初始常量序数为零。
(2) getDeclaringClass(): 通过枚举常量获取枚举类。
(3) toString() 和 name():在枚举类中name() 方法和toString() 方法返回的都是枚举常量的名称。
(4) values():返回一个以枚举类元素的数组
3.2 compareTo() 和 ordinal()
fun test5() {
var a: Int = Familier2.mother.compareTo(Familier2.son)
println("前者先声明,则返回 $a")
var b: Int = Familier2.daugther.compareTo(Familier2.son)
println("前者后声明,则返回 $b")
var c: Int = Familier2.son.compareTo(Familier2.son)
println("两者相同, 则返回 $c")
var d: Int = Familier2.father.ordinal
var e: Int = Familier2.daugther.ordinal
println("ordinal() 函数的值 d = $d, e = $e")
}
fun main(args: Array<String>) {
test5()
}
打印结果:
前者先声明,则返回 -1
前者后声明,则返回 1
两者相同, 则返回 0
ordinal() 函数的值 d = 0, e = 3
3.3 getDeclaringClass()
fun test6() {
var myClass = Familier2.son.declaringClass
println("通过调用 declaringClass 函数获得枚举类:${myClass.name}")
}
fun main(args: Array<String>) {
test6()
}
打印结果:
通过调用 declaringClass 函数获得枚举类:Familier2
3.4 toString() 和 name()
data class Leaf1(var size: String, var color: String, var shape: String, var vein: Int)
fun test7() {
var str1: String = Familier2.son.name
println("枚举类的 name 函数, str1 = " + str1)
var str2: String = Familier2.son.toString()
println("枚举类的 toString 函数, str2 = " + str2)
var leaf = Leaf1("20", "yellow", "circle", 30)
println("数据类的 toString 函数:" + leaf.toString())
}
fun main(args: Array<String>) {
test7()
}
打印结果:
枚举类的 name 函数, str1 = son
枚举类的 toString 函数, str2 = son
数据类的 toString 函数:Leaf1(size=20, color=yellow, shape=circle, vein=30)
还可以覆盖重写父类的 toString() 方法。如下代码所示:
enum class Familier3(var rank: Int) {
father(1), mother(2), son(3), daugther(4);
override fun toString(): String {
return "成员名称:" + this.name + ",成员排名:" + rank
}
}
fun test8() {
println("father = ${Familier3.father}, monther = ${Familier3.mother}")
println("toString() -- father = " + Familier3.father.toString() + ", monther " + Familier3.mother.toString())
println("name() -- father = " + Familier3.father.name + ", monther " + Familier3.mother.name)
}
fun main(args: Array<String>) {
test8()
}
打印结果:
father = 成员名称:father,成员排名:1, monther = 成员名称:mother,成员排名:2
toString() -- father = 成员名称:father,成员排名:1, monther 成员名称:mother,成员排名:2
name() -- father = father, monther mother
3.5 values()
fun test9() {
var lists: Array<Familier3> = Familier3.values()
println("家庭成员:" + lists.size)
for (list in lists) {
println(list)
}
}
fun main(args: Array<String>) {
test9()
}
打印结果:
家庭成员:4
成员名称:father,成员排名:1
成员名称:mother,成员排名:2
成员名称:son,成员排名:3
成员名称:daugther,成员排名:4
3.6 对应枚举类的 values() 方法获得的数组,枚举类也有一个自带的方法获取单个枚举常量,那就是 valueOf() 方法。举个栗子:
fun test10() {
var father = Familier3.valueOf("father")
var mother = Familier3.valueOf("mother")
var son = Familier3.valueOf("son")
var daughter = Familier3.valueOf("daugther")
var fatherMsg: String? = father.toString()
var motherMsg: String? = mother.toString()
var sonMsg: String? = son.toString()
var daughterMsg: String? = daughter.toString()
println("$fatherMsg \n$motherMsg \n$sonMsg \n$daughterMsg")
}
fun main(args: Array<String>) {
test10()
}
打印结果:
成员名称:father,成员排名:1
成员名称:mother,成员排名:2
成员名称:son,成员排名:3
成员名称:daugther,成员排名:4
在上述代码中,String 后面加了 ?,是因为并不能确定 valueOf() 是否真的会返回枚举类的实例。在数据类型后加一个 ?,即使返回的是一个空值,程序运行后也会打印一个空值,而不是报空指针的错误。
3.7 上面这些枚举类的方法描述都是“静态”的,能知道的信息有限,所以在项目中很多需求就需要通过自定义方法实现。举个栗子:
enum class Familier4(var rank: Int) {
father(1), mother(2), son(3), daugther(4);
override fun toString(): String {
return "成员名称:" + this.name + ",成员排名:" + rank
}
fun favoriteFood(): Unit {
when (this.name) {
"father" -> println("father like apple")
"mother" -> println("mother like banana")
"son" -> println("son like watermelon")
"daugther" -> println("daughter like peach")
else -> println("Familier do not have this person")
}
}
fun action() {
println("wo all like sports")
}
}
fun test11() {
print("${Familier4.father.toString()} ")
Familier4.father.favoriteFood()
print("${Familier4.mother.toString()} ")
Familier4.mother.favoriteFood()
print("${Familier4.son.toString()} ")
Familier4.son.favoriteFood()
print("${Familier4.daugther.toString()} ")
Familier4.daugther.favoriteFood()
Familier4.mother.action()
Familier4.daugther.action()
}
fun main(args: Array<String>) {
test11()
}
打印结果:
成员名称:father,成员排名:1 father like apple
成员名称:mother,成员排名:2 mother like banana
成员名称:son,成员排名:3 son like watermelon
成员名称:daugther,成员排名:4 daughter like peach
wo all like sports
wo all like sports
4. 枚举类的限制
4.1 枚举类的限制:不能再派生出子类 -- 即:不能继承和被继承。所以下面的代码,编译器是会直接报错的:
class SubEnumClass : EnumClass(){}
enum class SubEnumClass1: EnumClass(){}
enum class SubEnumClass2: Famililer(){}
4.2 枚举类其实隐性地继承了它的父类 Enum,所以它不能继承其他的类,但是枚举还是可以实现接口的。举个栗子:
interface OurFamily {
fun getNumOfRank(): Int
fun favoriteFood(): Unit
}
enum class Familier5() : OurFamily {
father, mother, son;
override fun getNumOfRank(): Int {
return 2
}
override fun favoriteFood() {
when (this.name) {
"father" -> println("father like apple")
"mother" -> println("mother like banana")
"son" -> println("son like watermelon")
else -> println("Familier do not have this person")
}
}
}
enum class Familier6(var rank: Int) : OurFamily {
father(1), mother(2), son(3), daughter(4);
override fun toString(): String {
return "成员名称:" + this.name + ",成员排名:" + rank
}
override fun favoriteFood() {
when (this.name) {
"father" -> println("father like apple")
"mother" -> println("mother like banana")
"son" -> println("son like watermelon")
"daugther" -> println("daughter like peach")
else -> println("Familier do not have this person")
}
}
fun action() {
println("wo all like sports")
}
override fun getNumOfRank(): Int {
return 1
}
}
fun test12() {
println("家庭1信息:家庭排名:${Familier5.father.getNumOfRank()}")
print("${Familier5.father.name} ")
Familier5.father.favoriteFood()
print("${Familier5.mother.name} ")
Familier5.mother.favoriteFood()
print("${Familier5.son.name} ")
Familier5.son.favoriteFood()
println("家庭2信息: 家庭排名: ${Familier6.daughter.getNumOfRank()}")
print("${Familier6.father.toString()} ")
Familier6.father.favoriteFood()
print("${Familier6.mother.toString()} ")
Familier6.mother.favoriteFood()
print("${Familier6.son.toString()} ")
Familier6.son.favoriteFood()
print("${Familier6.daughter.toString()} ")
Familier6.daughter.favoriteFood()
print("家庭2共同爱好:")
Familier6.daughter.action()
}
fun main(args: Array<String>) {
test12()
}
打印结果:
家庭1信息:家庭排名:2
father father like apple
mother mother like banana
son son like watermelon
家庭2信息: 家庭排名: 1
成员名称:father,成员排名:1 father like apple
成员名称:mother,成员排名:2 mother like banana
成员名称:son,成员排名:3 son like watermelon
成员名称:daughter,成员排名:4 Familier do not have this person
家庭2共同爱好:wo all like sports