前言
Kotlin中的类可以分为:数据类、密封类、枚举类 在开发中经常会用到。熟练掌握对我们以后开发是很重要的。
数据类
声明一个仅仅保存数据的类,用data关键字,放到class前面
data class Person(var name:String,var age:Int)
函数构造器中声明两个属性name和age。
- 数据类的主构造函数至少有一个参数
- 数据类主构造函数中的参数需要声明为
var或val
data calss Person(var name:String){
var age:Int = 18
}
Kotlin编译器为数据类Person生成toString equals hashCode copy 都涉及到name属性,不会涉及到age属性。包括ComponentN函数。
解构声明
数据类的主构造函数声明一个属性,Kotlin编译器会自动生成一个ComponentN函数与之顺序对应。可以通过点击Decompile查看反编译Java代码。 将Person对象接构成变量name和age
fun test() {
val (name,age) = Person("xiake",18)
}
data class Person(var name:String,var age:Int)
map遍历
fun test() {
val map = mapOf(0 to "A",1 to "B")
for ((key,value) in map){
println("key:$key value:$value")
}
}
输出:
key:0 value:A
key:1 value:B
使用解构声明将类型为Map.Entry<Int,String>对象解析成key value变量。可以在Lambda中使用解构声明。
fun test() {
normal { (name,age)-> println("name:$name age:$age") }
}
data class Person(var name:String,var age:Int)
private fun normal(block:(Person)->Unit){
block.invoke(Person("xiake",18))
}
函数有多个参数时,用逗号将解构和参数分开
fun test() {
normal { (name,age),from-> println("name:$name age:$age") }
}
data class Person(var name:String,var age:Int)
private fun normal(block:(Person,String)->Unit){
block.invoke(Person("xiake",18),"normal")
}
List集合可以使用解构声明,默认最多支持前5个元素
fun test() {
normal { (name,age),from-> println("name:$name age:$age") }
val (a,b,c,d,e) = listOf("A","B","C","E","F","G")
}
自kotlin1.1后,在解构声明中不需要某个变量,可以像Lambda参数一样,用下划线代替名称
val (name,_) = Person("xiake",18)
Kotlin编译器不会再调用相应的ComponentN函数
copy函数
在已有对象基础上稍作修改获取另一个新对象
fun test() {
val person = Person("xiake",18)
val nPerson = person.copy(name = "xiake2")
}
data class Person(var name:String,var age:Int)
copy函数实现类似如下
fun copy(name:String = this.name,age:Int = this.age) = Person(name,age)
Pair和Triple
kotlin内置数据类型。Pair类有两个属性参数,用中缀函数to创建Pair对象
val point = 10 to 100
用Pair扩展函数toList,将Pair对象转成List对象
val list = point.toList()
Triple声明了三个属性参数的数据类,提供了toList扩展函数
Triple(1,2,3).toList()
Tuples.kt源码
public data class Pair<out A, out B>(
public val first: A,
public val second: B
) : Serializable {
public override fun toString(): String = "($first, $second)"
}
public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
public fun <T> Pair<T, T>.toList(): List<T> = listOf(first, second)
public data class Triple<out A, out B, out C>(
public val first: A,
public val second: B,
public val third: C
) : Serializable {
public override fun toString(): String = "($first, $second, $third)"
}
public fun <T> Triple<T, T, T>.toList(): List<T> = listOf(first, second, third)
密封类
在kotlin中密封类使用sealed,放到calss之前
sealed class CrType
class Car: CarTpe()
calss SUV: CarType()
class BUS: CarType()
用来表示受限的类继承结构:一个值为有限的几种类型 不能有任何其他类型。像枚举类型的扩展:枚举类型的值集合也是受限的,每个枚举常量只存在一个实例 密封类的一个子类可以包含状态多个实例。使用密封类好处,当使用when表达式,只要覆盖到该密封类的所有子类型,无需编写else块
fun test() {
println(getCarName(Car()))
}
sealed class CarType
class Car :CarType()
class SUV :CarType()
class BUS :CarType()
fun getCarName(carType:CarType):String{
return when(carType){
is Car ->"Car"
is SUV ->"SUV"
is BUS ->"bus"
}
}
密封类本身是抽象的,没办法直接创建一个密封类对象,可以定义抽象方法或属性
sealed class CarType{
abstract val name:String
abstract fun info():String
}
枚举类
声明一个枚举类型关键字enum
enum class LoadState{
Success,
Failure
}
每个枚举类只存在一个实例。拥有一个name属性和一个ordlinal属性。name表示枚举类常量的名字,ordinal表示常量声明的顺序。用枚举的values()方法获取所有常量数组。
fun test() {
for (state in LoadState.values()){
println("name:${state.name} index:${state.ordinal}")
}
}
enum class LoadState{
Success,
Failure
}
输出:
name:Success index:0
name:Failure index:1
valuesof(String)方法通过指定名称获取具体的枚举常量,若通过名称未获取指定名称则抛出异常IllegalArgumentException:
fun test() {
println(LoadState.valueOf("hello"))
}
enum class LoadState{
Success,
Failure
}
异常:
No enum constant com.georege.leetcode2.ExampleUnitTest.LoadState.hello
java.lang.IllegalArgumentException: No enum constant com.georege.leetcode2.ExampleUnitTest.LoadState.hello
at java.base/java.lang.Enum.valueOf(Enum.java:273)
at com.georege.leetcode2.ExampleUnitTest$LoadState.valueOf(Test.kt)
at com.georege.leetcode2.ExampleUnitTest.test(Test.kt:14)
传入正确的枚举常量名称:
fun test() {
println(LoadState.valueOf(LoadState.Success.name))
}
enum class LoadState{
Success,
Failure
}
输出:
Success
在主构造函数给枚举类新增属性:
fun test() {
for (color in Color.values()){
println(color.rgb)
}
}
enum class Color(val rgb:Int){
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}
输出:
16711680
65280
255
和密封类一样,枚举本身是抽象类,可以添加抽象属性和方法:
fun test() {
for (state in LoadState.values()){
println(state.state)
}
}
enum class LoadState{
Success{
override val state = true
},Failure{
override val state = false
};
abstract val state:Boolean
}
输出:
true
false
在给枚举类添加抽象属性或方法,需要在声明最后一个枚举类使用分号;隔开。Kotlin1.1起,可使用enumValues<T>与enumValueOf<T>函数以泛型方式访问枚举类中的常量
fun test() {
printAll<LoadState>()
println(LoadState.Success)
}
enum class LoadState {
Success {
override val state = true
},
Failure {
override val state = false
};
abstract val state:Boolean
}
inline fun <reified T:Enum<T>> printAll(){
enumValues<T>().onEach { println(it.name) }
}
inline fun <reified R:Enum<R>> R.getEnum():Enum<R>{
return enumValueOf<R>(this.name)
}
输出:
Success
Failure
Success
总结
数据类、密封类、枚举类在Kotlin中经常用到,熟练掌握相关基础知识,对Kotlin开发是很重要的。