小狮子的Kotlin学习之路(十一)

Kotlin数据类和密封类

Kotlin中定义了一个仅包含数据的类,被称作数据类

数据类的声明方式为:

data class ClassName(var/val param, ...)

前面已经讲过了Kotlin的类,因此,我们仅了解一下数据类和普通的类有哪些区别,提供了哪些优势。

区别:

  1. 主构造函数至少需要包含一个参数。

  2. 所有的主构造函数的参数必须声明为val/var

  3. 数据类是不能被其他关键字修饰的,如abstractopensealed或者inner

  4. 数据类不能继承其他类(可以实现接口)。

接下来,我们定义一个数据类。

data class Student(var name: String, var age: Int, var address: String, val gender: String)

一般情况下,构造函数的参数不设置为private。因为对于数据类,编译器会自动从主构造函数中根据所有声明的属性提取一些函数。

  1. equals()hashCode()

  2. toString(),格式为Student(name = vicky, age = 18, ...)

  3. componentN()

  4. copy()

看完了,可能不知道有啥用是吧。其实这些都是data类的优点。

一、equals()/hashCode()就不用说了,可以方便的使用==来比较。

二、注意看格式后面,意味着可以直接输出对象,不用自己实现toString()函数。

三、componentN(),这个值得深入学习一下。

什么是componentN()函数呢,我们来看一个例子。

fun main() {
    val student = Student("vicky", 18, "Xi'an", "Male")
    val (name, age) = student
    println("name = $name, age = $age")
}

例子中可以看到,我们定义了一个变量val (name, age)使得它等于数据类对象student。这样,我们就可以直接使用这两个变量,相当于:

val name = student.name
val age = student.age

这还不是更重要的,比如我们可以这样声明:

fun main() {
    val student = Student("vicky", 18, "Xi'an", "Male")
    val (name, _, address, gender) = student
    println("name = $name, address = $address, gender = $gender")
}

我们看到有这样的变量声明:val (name, _, address, gender) = student。也就是说,通过数据类的解构声明,我们可以将不需要关注的值使用_代替。

Kotlin库提供了标准的数据类,如PairTriple。在某些对数据具体不太关注的情况下,可以直接使用,但是好的编程实践是,自定义并提供有意义的类名及属性名称。

四、copy(),顾名思义,就是对象拷贝,和克隆不一样的是,数据类的copy()可以拷贝并修改部分数据。

举个栗子:

fun main() {
    val student = Student("vicky", 18, "Xi'an", "Male")
    val goNewAddress = student.copy(address = "Shanxi")
    println(student)
    println(goNewAddress)
}

输出结果为:

我们看到,在拷贝了一个Student对象,并修改了它里面的address的值。这里我们也看到了,我们使用println(student)打印对象,输出的结果就是toString()方法生成的结果,并不像其他语言输出的是一个对象的地址。

关于数据类就差不多结束啦,接下来我们学习一下密封类

密封类其实比较简单,它的声明为:

sealed class ClassName(val/var param)

密封类用来表示受限的类继承结构:当一个值为有限几种的类型, 而不能有任何其他类型。

同样地,密封类不能使用其他关键字修饰(但是编译只报告警)。

密封类也可以有自己的子类,但是所有的子类必须定义在密封类中,并且子类需要重写equals()函数。

sealed class Fruits
data class Apple(var name: String): Fruits()
data class Orange(var name: String): Fruits()
object Tree : Fruits()

密封类如它的定义一样,它仅包含有限的几种类型,而我们前面学过的when表达式,搭配上密封类后,在匹配已知所有的类型后,便可以不需要else分支。至于它更多的便捷之处,等完全理解了之后并结合某些场景,可能会有更深的认知。

密封类并没有其他太多的内容,它和后面我们要介绍的枚举类很像。


微信扫码关注,惊喜多多

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值