每天学一点 Kotlin -- 多彩的类:枚举类

----《第一季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
相关代码:https://gitee.com/fzq.com/test-demo
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容