Kotlin快速入门系列7

Kotlin 的数据类 密封类 枚举类

数据类

与Java等语言不同,kotlin创建只包含数据的类时,需要在类名前声明关键字:data。

Kotlin 复制代码
data class KotlinBean (val brand : String)

在kotlin中,编译器会自动的从主构造函数中根据所有声明的属性提取以下函数:

· equals()
· hashCode()

· toString()

· componentN() functions (对应于属性,按声明顺序排列)

· copy()

如果这些函数已经在类中被明确定义了,或者从超类中继承而来,就不再会生成。不是所有的kotlin类都能声明为数据类,一般数据类声明都要满足以下条件:

· 主构造函数至少包含一个或多个参数;

· 所有的主构造函数的参数必须标识为val或var;

· 数据类不可声明为abstract,open,sealed或者inner;

· 数据类不能继承其他类(但是可以实现接口)。

Copy()

望词生意,此方法作用就是复制,我们可以使用该函数复制对象并修改部分属性,比如对于上面的KotlinBean类,实现类似下面示例:

Kotlin 复制代码
fun copy(brand: String = this.brand) = KotlinBean(brand)

需要修改数据类的属性时用copy(),示例:

Kotlin 复制代码
data class KotlinBean (val brand : String)

fun main(args: Array<String>) {
    val jack = KotlinBean(brand = "Jack")
    val olderJack = jack.copy(brand = "olderJack")
    println(jack)
    println(olderJack)
}

对应控制台命令输出为:

数据类及其解构声明

解构声明,kotlin允许展示单个复合值,并使用它来初始化多个单独的变量。例如:

Kotlin 复制代码
val pt=Point(111,222)
val (x,y)=pt
println(x) //打印111
println(y) //打印222

元组 ( 标准数据类 )

Kotlin的标准库提供了Pair(元组)和Triple(三元元组),可以把多个值同时赋给一个变量,或者同时给多个变量赋值。在新版的Kotlin中已经删除了多元元组,也就是只有Pair和Triple。

通常我们在对变量进行赋值时,只能附带一个值,例如:

Kotlin 复制代码
val name = "batman"

通过元组对变量进行多个赋值,构造时也都可以通过泛型指定各个位置的对象类型:

Kotlin 复制代码
fun main(args: Array<String>) {
    val batMan = Triple<String,String,Int>("Bluce","technology",10000)
    val jokerMan = Pair<String,String>("joker","Gotham")
    println(batMan.first)
    println(batMan.second)
    println(batMan.third)
    println("----------------------")
    println(jokerMan.first)
    println(jokerMan.second)
}

对应的控制台输出为:

可以发现Kotlin的元组在进行单独类多数据交互情景下比Java友好(Java还要先声明一个bean类然后进行set/get操作)。值得一提的是,上述示例也用到了元组的常用API,比如Pair的:

Kotlin 复制代码
pair.first    //获取第一个元素
pair.second   //获取第二个元素

Tuples的方法:

Kotlin 复制代码
tuples.first  //获取第一个元素
tuples.second //获取第二个元素
third.third //获取第三个元素

两个类还都有toList()方法可以把存储的对象转化为List,这里不做赘述。

密封类

密封类用于表示受限制的类层次结构,当一个值只能在一个集合中取值时,而不能取其他值时。在某种意义上,这是枚举类的扩展(枚举类型的值集合也是受限的,但每个枚举常量只存在一个实例,而密封类的一个子类可以有可包含状态的多个实例)。

声明密封类,需要用关键字sealed来修饰。被sealed修饰的类默认是open的,所以可以被继承,而不需要显式使用open修饰符。虽然密封类可以有子类,但是所有的子类必须要内嵌在密封类中。

sealed不能修饰interface,abstract class(会报warning,但是不会出现编译错误)

Kotlin 复制代码
sealed class SealedClass{
    class ExtendClass1: SealedClass(){

    }

    class ExtendClass2: SealedClass(){

    }
}

fun check(sealedClass: SealedClass): String =
    when(sealedClass){
        is SealedClass.ExtendClass1 -> "1"
        is SealedClass.ExtendClass2 -> "2"
    }

在密封类中使用 when 表达式 的时候,如果能够验证语句覆盖了所有情况,就不需要为该语句再添加一个 else 子句了。

枚举类

枚举类就是一组命名的常数,是指将变量的值一一列举出来,变量的值只限于列举出来的值的范围内。

枚举类的最基本的用法是实现类型安全的枚举,其中枚举常量用逗号分隔,每个枚举常量都是一个对象。

Kotlin 复制代码
enum class Color{
    RED,YELLOW,BLUE,GREEN
}

枚举初始化

每一个枚举都是枚举类的实例,它们都可以被初始化:

Kotlin 复制代码
enum class Color(val rgb: Int) {
    RED(0xFF0000),
    YELLOW(0xFFFF00),
    GREEN(0x00FF00),
    BLUE(0x0000FF)
}

通常用法也较简单:

Kotlin 复制代码
fun main(args: Array<String>) {
    println(Color.YELLOW.name)
    println(Color.YELLOW.ordinal)
}

对应的控制台输出为:

细心的你肯定会发现上述的两个参数.name和.ordinal。在枚举类中,每个枚举常量都具有在枚举类声明中获取其名称与位置的属性:

Kotlin 复制代码
val name: String   //名称
val ordinal: Int   //枚举值所在枚举数组中定义的顺序

换言之,每个枚举类中的常量都可以 .name 拿到名称,.ordinal 拿到位置(从0开始算起)。

如果要指定位置,则可以使用其构造函数:

Kotlin 复制代码
enum class Shape(value:Int){
    ovel(100),
    rectangle(200)
}

枚举类还支持以声明自己的匿名类及相应的方法、以及覆盖基类的方法。例如:

Kotlin 复制代码
enum class Fruit {
    EATING {
        override fun signal() = DRINKING
    },

    DRINKING {
        override fun signal() = EATING
    };

    abstract fun signal(): Fruit
}

这里要注意的是,如果枚举类定义任何成员,要使用分号将成员定义中的枚举常量定义分隔开。

使用枚举常量

Kotlin 中的枚举类具有合成方法,允许遍历定义的枚举常量,并通过其名称获取枚举常数。(假设枚举类的名称是 EnumClass)格式如下:

Kotlin 复制代码
EnumClass.valueOf(value: String): EnumClass  // 转换指定 name 为枚举值,若未匹配成功,会抛出IllegalArgumentException
EnumClass.values(): Array<EnumClass>        // 以数组的形式,返回枚举值

对应的简单示例如下:

Kotlin 复制代码
enum class Color {
    RED,
    YELLOW,
    BLUE,
    GREEN
}

fun main(args: Array<String>) {
    var color:Color=Color.BLUE
    println(Color.values())
    println(Color.valueOf("RED"))
    println(color.name)
    println(color.ordinal)
}

相应的控制台输出为:

枚举常量还实现了 Comparable 接口,其中的自然顺序是它们在枚举类中定义的顺序,对此接口有兴趣的可以自己去尝试实现验证。

End,如有问题请留言交流。

相关推荐
湫ccc11 分钟前
《Python基础》之字符串格式化输出
开发语言·python
mqiqe1 小时前
Python MySQL通过Binlog 获取变更记录 恢复数据
开发语言·python·mysql
工业甲酰苯胺1 小时前
MySQL 主从复制之多线程复制
android·mysql·adb
AttackingLin1 小时前
2024强网杯--babyheap house of apple2解法
linux·开发语言·python
少说多做3431 小时前
Android 不同情况下使用 runOnUiThread
android·java
Ysjt | 深1 小时前
C++多线程编程入门教程(优质版)
java·开发语言·jvm·c++
ephemerals__2 小时前
【c++丨STL】list模拟实现(附源码)
开发语言·c++·list
码农飞飞2 小时前
深入理解Rust的模式匹配
开发语言·后端·rust·模式匹配·解构·结构体和枚举