介绍
除了与Java类比的这些功能之外,Kotlin还新增了一些新的概念
- 数据类(data)
- 扩展函数
- 密封类(sealed)
- 匿名类
- 伴生对象(Companion)
数据类
通过data
关键字来定义数据类。通常用来定义纯数据类型的结构体。定义的数据类只能有一个主构造函数定义该数据类中的变量。而在该类中,可以定义函数
data class Date(var year: Int = 10,
var month: Int,
var day: Int) {
fun getDay(): String {
return "year:$year...month:$month...day:$day"
}
}
扩展函数
在Java中,如果有一个数据类需要转换成各种格式的结构,或者需要对属性做一些处理返回,通常会通过util
或者wrappe
来对数据结构做封装。而在Kotlin中提供了扩展函数可以来完成这一些操作。
我们可以在使用的类中,通过以下方式来定义类的扩展函数。但是该扩展函数的使用范围仅在这个类中使用。而该函数内有this
指针,代表着调用该函数的对象,可以直接访问这个对象的成员
fun ClassName.Function():ReturnType{
// TODO
}
例如:接上述代码,有一个类Date
代表日期,在Child
类中,代表生日,而在Product
类中代表生产日期。那么就可以:
open class Child(name: String, age: Int = 18) : AbsPerson(name) {
override var mAge = age
fun childBirthDay(date: Date): String {
return date.birthDay()
}
fun Date.birthDay(): String {
return "Child BirthDay ${this.getDay()}...${this.year}"
}
}
而在Product
类中,可以直接通过Date.craeteDay
来调用:
class Product {
fun createDay(date: Date) {
date.creatDay()
}
fun Date.creatDay() {
this.getDay()
}
}
通过扩展函数的方式来完成对与数据类以及其他类的隔离,保证各个类之间的隔离。同样,Kotlin也支持扩展属性,与函数类似定义。
密封类
密封类用来表示受限制的类继承结构。由于enum
每一个实例都是一个常量,所以密封类被开发,密封类的子类可以有多个实例。
声明密封类后,也可以定义多个子类,但是这些子类都需要在与密封类同一个文件中。
// 声明SealedClass类
sealed class SealedClass
// 定义数据类继承自SealedClass
data class SealedDataClass(var data: Int) : SealedClass()
// 定义通用类继承自SealedClass
class SealedConstClass : SealedClass()
而它的用处最经典的是,在when
子句中判断类型
fun choose(data: SealedClass) {
when(data){
is SealedConstClass -> data.hashCode()
is SealedDataClass -> data.value
}
}
匿名类
Java中可以通过new
关键字创建匿名类,而Kotlin中则通过object
关键字来定义匿名类。
通过函数返回的匿名对象必须是private
声明的函数。否则无法解析。而匿名类也可以继承类:
class Teenager {
fun runFast() {
var round = object {
var time: Long = 0
var distance: Long = 0
}
round.time = 10
round.distance = 100
var round2 = runFast2()
round2.distance = 100
round2.time = 10
round2.walk()
}
private fun runFast2() = object : Child("Bob") {
var time: Long = 0
var distance: Long = 0
}
}
伴生对象(Companion)
用伴生对象声明的对象,与类没有什么关系,可以使用类名直接调用,例如在实现单例的时候可以直接使用。
class Teenager private constructor() {
companion object Teen {
var teenager: Teenager = Teenager()
}
fun runFast() {
Log.e("Tag", "runFast")
}
}
在使用的时候,可以直接访问并且调用
Teenager.teenager.runFast()
如果不使用companion
修饰的话,则需要调用
Teenager.Teen.teenager.runFast()
可以理解成如果没有使用companion
修饰的话,object
只是声明了一个匿名类的对象,而对象名为Teen
,然后通过这个对象访问teenager
。如果使用companion
的话,则可以直接访问teenager