简单即是美

在之前的三篇文章中,我们已经了解了一下的内容:

  1. 如何在项目中使用 Kotlin,Kotlin 的空安全
  2. 集合的相关操作,扩展函数以及 Lambda 表达式等高级特性
  3. for 与集合遍历,强大的 if 、when 表达式,可以用来做单例模式的伴生对象

数据类

你是否已经厌烦了一个项目中大量的 POJO ?是的,虽然我们有大量的插件来帮助我们简化这些创建过程,但是满天的 gettersetter 还有那些 equals()/hashCode() 大量机械的、重复的方法。

Kotlin 为我们提供了更强大数据类,如下所示:

data class User(var name: String="", var age:Int = 0){
    var nickname:String = ""
}

使用 data 关键字来告知系统这是一个数据类,其主构造函数需要至少有一个参数,如果生成的类需要含有一个无参的构造函数,则所有的属性必须指定默认值。

请注意,对于那些自动生成的函数,编译器只使用在主构造函数内部定义的属性。如需在生成的实现中排出一个属性,请将其声明在类体中。

自动生成的函数只是用主构造函数定义的属性

复制一个数据类

复制数据类的两个方式

当我们使用 copy 函数时,系统会找到该类的主构造函数的签名,此时我们可以按顺序填入参数(无需完全填写,会从第一位开始自动匹配),还可以采用类似 Python 的方式 参数名 = 值的方式来修改我们需要的参数值。

解构声明

这四个字对于 Android + Java 开发者是挺陌生的,大家可以点击到 Kotlin 中文站查看详细的定义,下面我们通过代码来了解一下他的用法,首先我们来看一张熟悉的图:
for 循环遍历 Map 集合

注意这里的 (k,v) 这就是一个解构声明,标准库已经帮我们实现了解构声明,另外数据类也已经实现了主构造函数包含参数的解构声明。

比如刚刚我们创建的 User 类,我们可以通过如下的方式来获取其中指定的值:

var (name,age) = c
var (_,aged) = d  //用下划线占位不需要的参数
var aged1 = d.component2()  //直接使用 componentN 函数来获取对应的值
println("c's name = $name c's age = $age")
println("don't need d's name, d's age = $aged")
println("other way to get d's age is $aged1")

我们可以任意的在类中进行解构声明,比如我们可以使用解构声明来扩展刚刚我们定义的 User 类:

data class User(var name: String="", var age:Int = 0){
    var nickname:String = ""

    operator fun component3() = nickname
}

需要注意的是,数据类默认为我们实现了主构造函数的参数解构声明,所以我们的解构声明只能接着主构造函数的序号往后使用

自定义的解构声明

在 Lambda 表达式中使用解构声明

当这个类进行了解构声明时,我们可以直接在 Lambda 表达式中使用其解构,如下:

c.let { (a,b,c) ->
            println("c's name = $a , c's age = $b , c's nickname = $c")
        }

请注意解构声明对于 Lambda 表达式而言是一个参数:

{ a //-> …… } // 一个参数
{ a, b //-> …… } // 两个参数
{ (a, b) //-> …… } // 一个解构对
{ (a, b), c //-> …… } // 一个解构对以及其他参数

在函数中返回数个参数

有的时候我们经常会希望一个函数能返给我们多个结果,例如曾经我做过一个小功能:传入 PM2.5 的值,返回当前 PM2.5 严重程度的介绍以及需要显示的颜色代码。当时我采用的做法是返回一个 Map,然后再需要的地方在使用固定的 key 将值提取出来,这一点也不优雅。

但是在 Kotlin 里 你可以这样做:

    fun getPM25DescAndColor(pm25: Int):Pair<String,String> {
        return when (pm25) {
            in 0..50 -> Pair("优秀","#009900")
            in 51..100 -> Pair("良好","#FFCC33")
            in 101..150 -> Pair("轻度","#FF9900")
            in 151..200 -> Pair("中度","#FF3300")
            in 201..300 -> Pair("重度","#9900FF")
            else -> Pair("严重","#663300")
        }
    }

标准库提供了 PairTriple 这两个类,前者表示两个参数,后者表示三个参数。尽管在很多情况下命名数据类是更好的设计选择, 因为它们通过为属性提供有意义的名称使代码更具可读性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章