系列文章全部为本人的学习笔记,若有任何不妥之处,随时欢迎拍砖指正。如果你觉得我的文章对你有用,欢迎关注我,我们一起学习进步!
Kotlin学习笔记(1)- 环境配置
Kotlin学习笔记(2)- 空安全
Kotlin学习笔记(3)- 语法
Kotlin学习笔记(4)- 流程控制
Kotlin学习笔记(5)- 类
Kotlin学习笔记(6)- 属性
Kotlin学习笔记(7)- 接口
Kotlin学习笔记(8)- 扩展
Kotlin学习笔记(8)- 扩展(续)
Kotlin学习笔记(9)- 数据类
Kotlin学习笔记(10)- 泛型
Kotlin学习笔记(11)- 内部类和嵌套类
Kotlin学习笔记(12)- 委托
Kotlin学习笔记(13)- 函数式编程
Kotlin学习笔记(14)- lambda
这些天项目比较忙,一直在加班,现在周末了,赶紧把kotlin拿起来,继续学习~
一、定义
在平时的使用中,我们会用到一些类来保持一些数据或状态,我们习惯上成为bean
或者entity
,也有的定义为model
。kotlin中有专门处理这一种类的关键字:data。
data class PersonData(var name : String, var age : Int)
这种由data修饰的类叫做数据类,编译器自动从在主构造函数定义的全部特性中得到以下成员:
-
equals()
/hashCode()
-
toString()
格式是"PersonData(name=PersonData, age=20)"
-
componentN()
方法对应按声明顺序出现的所有属性 -
copy()
方法
如果有某个函数被明确地定义在类里或者被继承,编译器就不会生成这个函数。
上面是官方说法,换成通俗的说就是,如果在数据类里自定义了equals
等某个方法,那编译器就不会再去生成它。
总结一下,数据类的定义就是以下几个特点:
- 类由关键字
data
修饰(好像是废话) - 类的构造参数必须由
var
/val
修饰,否则编译不通过 - 编译器会自动生成一些常用方法,你可以自定义它们
- 和普通类一样,如果你需要一个无参构造方法,可以将构造方法的参数都设置默认值
二、toString
如果没有自定义的话,编译器会自动生成toString
方法,输出格式为类名+参数的顺序值
// 定义数据类和普通类
data class PersonData(var name : String, var age : Int)
class PersonNormal(var name : String, val age : Int)
// 分别初始化并进行toString输出
fun test(){
var personD = PersonData("PersonData", 20)
var personN = PersonNormal("PersonNormal", 20)
Log.d("test", personD.toString())
Log.d("test", personN.toString())
}
// 输出
PersonData(name=PersonData, age=20)
com.study.jcking.weatherkotlin.exec.PersonNormal@26b13e2
三、复制copy
copy方法可以让我们方便的对数据类进行赋值,甚至是有修改的复制。比如我们上面写道的PersonD
,如果我们想对它进行赋值,并且将名字改为PersonCopy
var personC = personD.copy("Person Copy")
Log.d("test", personC.toString())
//输出
PersonData(name=Person Copy, age=20)
我们只需要传递我们要修改的部分,编辑器会自动识别。上面的写法大概是这种实现
fun copy(name: String = this.name, age: Int = this.age) = PersonData(name, age)
如果我们的构造参数中有多个参数类型一致,上面的写法会按定义的顺序优先匹配
data class PersonData(var name : String, var age : Int, val sex : String)
var personD = PersonData("PersonData", 20, "male")
var personC = personD.copy("famale")
Log.d("test", personC.toString())
// 输出
PersonData(name=famale, age=20, sex=male)
其实很明显的,我们要修改的是sex
,也就是第三个参数。这时候需要指定参数名
var personC = personD.copy(sex = "famale")
// 输出
PersonData(name=PersonData, age=20, sex=famale)
OK,完美
四、多声明
多声明,也可以理解为变量映射,这就是编译器自动生成的componentN()
方法。
var personD = PersonData("PersonData", 20, "male")
var (name, age) = personD
Log.d("test", "name = $name, age = $age")
//输出
name = PersonData, age = 20
上面的多声明,大概可以翻译成这样
var name = f1.component1()
var age = f1.component2()
五、序列化
由于我们的项目中,要求所有数据类都序列化,那么在学习kotlin时自然就想到了数据类的序列化问题。在Android Studio上,java的数据类可以通过Parcelable
插件自动进行序列化,kotlin中暂时不能用,只能自己实现。实现方法和java中的手动实现基本一致。
data class PersonData(var name : String, var age : Int, val sex : String) : Parcelable{
override fun writeToParcel(p0: Parcel?, p1: Int) {
p0?.writeString(this.name)
p0?.writeInt(this.age)
p0?.writeString(this.sex)
}
override fun describeContents(): Int {
return 0
}
constructor(source: Parcel) : this(source.readString(), source.readInt(), source.readString())
companion object {
@JvmField val CREATOR: Parcelable.Creator<PersonData> = object : Parcelable.Creator<PersonData> {
override fun createFromParcel(source: Parcel): PersonData {
return PersonData(source)
}
override fun newArray(size: Int): Array<PersonData?> {
return arrayOfNulls(size)
}
}
}
}