kotlin进阶篇(一)

/ 0评 / 0

  相信我们经过基础篇的学习应该对Kotlin有了初步的认识,本篇将进一步讲解Kotlin语法知识,并学习一些开发中的使用技巧。

安全调用运算符: "?."

"?."将一次null检查和一次方法调用合成一个操作,例如: view?.renderNickname(),如果不使用该操作符将等同于: if(view != null) view.renderNickname() , 如你所见 "?.” 操作符使代码看起来更为简洁。

Elvis运算符: “?:”

该运算符亦被称作null合并运算符,它提供代替null的默认值。例如:val str = tempStr ?: "abc" ,elvis操作符接受两个运算数,如果第一个运算数不为null,运算结果就为第一个运算数;如果第一个运算数为null,运算结果则为第二个操作符。

非空断言: "!!"

非空断言可将任何值转换成非空类型。如果对null值做非空断言则会抛出空指针异常。开发中如果不确定某个变量的取值情况下尽量不要使用非空断言。非空断言的使用方式:view!!.renderFeed(feeds)

as操作符

该操作符可为import提供重命名操作, 例如: import com.squareup.leakcanary.LeakCanary as LC , 然后通过临时名称使用该导入模块,例如:LC.install(this) 。as操作符亦可作为类型转换工具使用,例如:val activity = context as Activity

let函数

函数定义:

fun <T, R> T.let(f: (T) -> R): R = f(this)

和安全调用运算符一起使用,它允许对表达式求值,检查求值结果是否为null,默认当前对象作为闭包的it参数,返回值是函数里面的最后一行。例如:

fun testLet() {
 view?.let {
            it.showRefreshCompleted()
             it.renderFeeds(feeds) 
}

with函数

函数定义:

fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()

该函数把它的第一个参数转换成作为第二个参数传给他的lambda的接受者,可以显示的通过this访问这个接收者。例如:

fun testWith() {
    with(ArrayList<String>()) {
        add("testWith")
        add("testWith")
        add("testWith")
        println("this = " + this)
    }
}

apply函数

函数定义:

fun <T> T.apply(f: T.() -> Unit): T { f(); return this }

apply函数几乎和with函数一模一样,唯一的区别就是apply始终会返回作为实参传递给它的对象。例如:

fun testApply() {
    ArrayList<String>().apply {
        add("testApply")
        add("testApply")
        add("testApply")
    }.let { println(it) }
}

run函数

函数定义:

fun <T, R> T.run(f: T.() -> R): R = f()

在run中,用this代表当前引用对象,并且调用其方法时,this可省略。
返回值是语句块的最后一行,若最后一行语句无返回值,则整个run语句块也无返回值。

fun testRun() {
    val list: MutableList<String> = mutableListOf("A", "B", "C")
    val change: Any
    change = list.run {
        add("D")
        add("E")
        this.add("F")
        size
    }
    println("list = $list")
    println("change = $change")
}

输出:

list = [A, B, C, D, E, F]
change = 6

高阶函数

高阶函数可以将一个函数作为参数或者返回值,方法形参传入加上"::"操作符。例如:

 fun add(x: Int = 0, y: Int = 0): Int {
    return x + y
 }

 fun operate(x: Int = 0, y: Int = 0, func: (Int, Int) -> Int) {
    print(func(x, y))
 }

 fun getValue() {
    operate(1, 2, ::add)
 }

Lambda表达式

Lambda 表达式的完整语法形式,即函数类型的字面值如下:

val sum = { x: Int, y: Int -> x + y }

lambda 表达式总是被大括号括着, 完整语法形式的参数声明放在括号内,并有可选的类型标注, 函数体跟在一个 -> 符号之后。如果推断出的该 lambda 的返回类型不是 Unit类型,则 lambda 主体中的最后一个表达式将会视为返回值。其次,当函数参数是函数的最后一个参数并且传入一个lambda表达式作为相应的参数时,可以在括号外指定它,例如:

fun getValue1() {
    operate(1, 2,{
        x, y -> x + y
    }) 
}

fun getValue2() {
    operate(1, 2) {
        x, y -> x + y
    }
}

如果lambda表达式只有一个参数,kotlin可以推算出签名,则我们可以不用声明唯一的参数,它将为我们隐式声明为名为it,例如:

button.setOnClickListener { it.isEnabled = false }

如果lambda表达式是调用的唯一参数,则调用中的圆括号可以完全省略:

fun String.upper(body: (String) -> String): String {
    return body(this)
}

fun transform() {
    "Kotlin".upper { it.toUpperCase() }
}

匿名函数

匿名函数与常规函数一样,只是省略了函数名称而已:

fun String.upper(body: (String) -> String): String {
    return body(this)
}

fun transform() {
    "Kotlin".upper(fun(str: String): String {
        return str.toUpperCase()
    })
}

Lambda表达式和匿名函数之间的另一个区别是非局部返回的行为。具体指一个不带标签的 return 语句总是在用 fun 关键字声明的函数中返回。 lambda 表达式中的 return 将从包含它的函数返回,而匿名函数中的 return 将从匿名函数自身返回。

fun foo() {
    numbers.forEach {
        if (it == 0) return
        print(it)
    }
}

值得注意的是:这种非局部的返回只支持传给内联函数的 lambda 表达式。 如果我们需要从 lambda 表达式中返回,我们必须给它加标签并用以限制 return。

fun transform(): String {
    "Kotlin".upper {
        print(it.toUpperCase())
        return@upper it.toUpperCase()
    }
    "Kotlin".upper(fun(str:String): String {
        return str.toUpperCase()
    })
}

  本篇介绍了Kotlin语言中的操作符、转换函数、lambda等,下篇将重点讲解下Kotlin语言级委托机制。

发表评论

电子邮件地址不会被公开。 必填项已用*标注