Kotlin使用关键字解释、基本规范分享

经过初步的学习,在项目中使用了一段时间kotlin后,汇总小组各个成员的心得体会,在此做个记录。

operator关键词 操作符重载

 使用举例
  ```kotlin
   val mOnClickCallBack1: (Int) -> Unit =
        { position -> Toast.makeText(this, "position:$position", Toast.LENGTH_LONG).show() }
   val mOnClickCallBack2: OnItemClickCallback = object : OnItemClickCallback {
        override fun invoke(position: Int) {
            Toast.makeText(this@MainActivity, "position:$position", Toast.LENGTH_LONG).show()
        }
    }
  mBtApp.setOnClickListener(object : View.OnClickListener {
        override fun onClick(v: View?) {
            mOnClickCallBack1(1)
            mOnClickCallBack1.invoke(1)
            mOnClickCallBack2.invoke(1)
           //mOnClickCallBack2(1)//想这么使用需要用operator重载 invoke方法
        }
    })
 ```

标准函数的使用选择

10069305-9098acc2fbba7a58.png

总结如下:
需要返回本身this 用apply、also
传递this作为参数用apply 传递it用also

不需要返回本身this 用run let with
需要空检查 用run let 不需要空检查用with
传递this作为参数用run with 传递it作为参数用let

成员变量不稳定性

成员变量具有不稳定性,非空判断并不能将其自动转换为非空类型
使用举例

{
      mWeather = Weather("25C", "雨", true)
      //if (mWeather!=null){ 
      //    mWeather.temp
      //}
      //应如下使用:
      mWeather?.temp
}

lateinit Lazy 使用说明

lateinit 就是一个修饰符 被修饰的变量不用做非空校验
Lazy 是一种代理,真正的懒加载对性能有提升

reified 关键词说明

这个单词,也是起的有点犀利,reified 翻译一下就是: 具体化。可以理解为 具体化一个东西。
常用在泛型的具体化
见:package org.jetbrains.anko Intents.kt startActivity

open

使用带open关键词的val对象,来设计基类。可以让这个成员变量又是val类型不可修改,又可以在子类中更改

open val likeDataProvideListener: (() -> CardLikeRequestData)? = null

!!

尽量不要让代码中出现!!强行忽略空判断,大量使用!!的时候需要看一下是否是设计出了问题,该变量是否可以设计成非空类型。

如果实现了java的一个接口,kotlin可能会默认将其中的参数类型设置为可能为空,如果确定在这里不会为空的时候可以直接删除 ? 且不会报错。

多使用闭包

可以使用闭包来代替一些简单的接口

open val likeDataProvideListener: (() -> CardLikeRequestData)? = null

it嵌套

如果有多个 let 函数嵌套的时候,会出现 it 嵌套的情况,这种时候会对当前 it 是什么造成疑惑。这种情况要给后面的 it 修改命名。

扩展函数

Collection和String有大量的扩展函数,使用起来会很方便

Collection 扩展函数

  1. .forEach 扩展函数,遍历集合
  2. .isNullOrEmpty 扩展函数,判断集合是null或者为空
  3. .forEachWithIndex 扩展函数,遍历集合并且可以拿到index
  4. .lastIndex 扩展属性,最后一个index

String 扩展函数

  1. .isNullOrBlank 扩展函数,是null或者长度为0或者只有空格
  2. .isNullOrEmpty 扩展函数,是null或者长度为0

?: return

在执行逻辑的时候,可能会有类似下面这样的代码

// a的类型为A? A中有一个属性b类型为B?
val b :B? = a?.b ?: null
// 此时b的类型为 B?
if (b != null) {
    // dosomething
}

这种时候可以替换成

val b :B = a?.b ?: return
// 此时b的类型为 B
// dosomething

让代码更简洁

Kotlin实现Parcelable

方法一:使用注解
1.在gradle中添加
android {
...
//使用Kotlin实验特性
androidExtensions {
experimental = true
}
}
2.使用注解标记数据类并实现Parcelable接口

@Parcelize
data class User(val name: String, val age: Int) : Parcelable

方法二
AS搜索Parcelable Code Generator(for kotlin)插件安装

lambda表达式

1、lambda表达式始终存在于一对{}中,如下:

图片.png

2、 高阶函数(形参)

高阶函数就是以另一个函数作为参数或返回值的函数
如果用 lambda 来作为高价函数的参数(此时为形参),就必须先了解如何声明一个函数的形参类型,如下:


图片.png
// printSum 为高阶函数,定义了 lambda 形参
fun printSum(sum:(Int,Int)->Int){
        val result = sum(1, 2)
        println(result)
}
// 以下 lambda 为实参,传递给高阶函数 printSum
val sum = {x:Int,y:Int->x+y}
printSum(sum)

有了高阶函数,我们可以很轻易地做到一个 lambda 嵌套另一个 lambda 的代码结构

3、大括号放在最后

Kotlin 的 lambda 有个规约:如果 lambda 表达式是函数的最后一个实参,则可以放在括号外面,并且可以省略括号,如:

person.maxBy({ p:Person -> p.age })
// 可以写成
person.maxBy(){
    p:Person -> p.age
}
// 更简洁的风格:
person.maxBy{
    p:Person -> p.age
}

4、带接收者的 lambda

图片.png

带接收者的 lambda 丰富了函数声明的信息,当传递该 lambda值时,将携带该接收者,比如:

// 声明接收者
fun kotlinDSL(block:StringBuilder.()->Unit){
  block(StringBuilder("Kotlin"))
}
// 调用高阶函数
kotlinDSL {
  // 这个 lambda 的接收者类型为StringBuilder
  append(" DSL")
  println(this)
}

总而言之,lambda 在 Kotlin 和 Kotlin DSL 中扮演着很重要的角色,是实现整洁代码的必备语法糖。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容