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
分支。至于它更多的便捷之处,等完全理解了之后并结合某些场景,可能会有更深的认知。
密封类并没有其他太多的内容,它和后面我们要介绍的枚举类很像。