美文网首页
每天学一点 Kotlin -- 多彩的类:枚举类

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

作者: 冯可乐同学 | 来源:发表于2021-11-23 11:09 被阅读0次

    ----《第一季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

    相关文章

      网友评论

          本文标题:每天学一点 Kotlin -- 多彩的类:枚举类

          本文链接:https://www.haomeiwen.com/subject/brytaltx.html