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,如有问题请留言交流。

相关推荐
Scott9999HH1 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社2 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海2 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖3 小时前
JDK 26 新特性详解
java·开发语言
马优晨4 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区6 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大6 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai6 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜7 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa7 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio