美文网首页
每天学一点 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