小狮子的Kotlin学习之路(十一)
Kotlin数据类和密封类Kotlin中定义了一个仅包含数据的类,被称作数据类。数据类的声明方式为:data class ClassName(var/val param, ...)前面已经讲过了Kotlin的类,因此,我们仅了解一下数据类和普通的类有哪些区别,提供了哪些优势。区别:主构造函数至少需要包含一个参数。所有的主构造函数的参数必须声明为val/var...
Kotlin数据类和密封类
Kotlin中定义了一个仅包含数据的类,被称作数据类。
数据类的声明方式为:
data class ClassName(var/val param, ...)
前面已经讲过了Kotlin的类,因此,我们仅了解一下数据类和普通的类有哪些区别,提供了哪些优势。
区别:
-
主构造函数至少需要包含一个参数。
-
所有的主构造函数的参数必须声明为
val/var。 -
数据类是不能被其他关键字修饰的,如
abstract、open、sealed或者inner。 -
数据类不能继承其他类(可以实现接口)。
接下来,我们定义一个数据类。
data class Student(var name: String, var age: Int, var address: String, val gender: String)
一般情况下,构造函数的参数不设置为private。因为对于数据类,编译器会自动从主构造函数中根据所有声明的属性提取一些函数。
-
equals()或hashCode()。 -
toString(),格式为Student(name = vicky, age = 18, ...)。 -
componentN()。 -
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库提供了标准的数据类,如Pair和Triple。在某些对数据具体不太关注的情况下,可以直接使用,但是好的编程实践是,自定义并提供有意义的类名及属性名称。
四、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分支。至于它更多的便捷之处,等完全理解了之后并结合某些场景,可能会有更深的认知。
密封类并没有其他太多的内容,它和后面我们要介绍的枚举类很像。
更多推荐

所有评论(0)