kotlin介绍与基本使用

Lambda

可理解为一段代码块,{ }包围,可当做值进行传递,lambda是未声明的函数,以表达式的形式传递

val sum = {num1: Int, num2: Int -> num1 + num2}

-> 前为参数列表,-> 后为要执行的函数体。参数需指定参数类型,若可以推断出类型,可以省略。

val sum2: (x: Int, y: Int) -> Int = { num1, num2 -> num1 + num2 }

把lambda作为函数的参数传递(高阶函数)的简化
定义高阶函数:

private fun testLambdaFun(num1: Int, num2: Int, opt: (x: Int, y: Int) -> Int): Int {
			return opt(num1, num2)
}

接收两个Int类型的参数和一个lambda表达式,返回Int类型,lambda表达式的参数是两个Int类型,返回Int类型

调用的几种方式

1.lambda作为变量

testLambdaFun(1, 2, sum)

2.直接传递lambda表达式

testLambdaFun(1, 2, { num1, num2 -> num1 + num2 })

3.lambda表达式是函数的最后一个参数,可移到括号外

testLambdaFun(1, 2) { num1, num2 -> num1 - num2 }

4.除lambda表达式外没有其他参数 () 也可省略

btn.setOnClickListener { v -> ToastUtils.showShort("click") }

btn.setOnClickListener { ToastUtils.showShort("click") }

单个参数可省略,如需使用可用 it 指代

使用lambda可以简化java中匿名内部类的使用,如上面的设置点击监听的方法,像这种只有一个抽象方法的接口称为函数式接口(SAM接口),都可以使用lambda来替代匿名内部类的方式

匿名内部类中只能使用final类型的局部变量,lambda表达式中没有这一限制,可以使用、修改局部变量

常与集合配合使用,kotlin标准库中有很多操作集合的函数如 filter map maxByOrNull all any count find 等

内联函数 inline

编译时期就将函数体替换到调用该函数的地方,节省运行时函数调用的开销
常用的自带内联函数 let with run apply also

let函数

public inline fun <T, R> T.let(block: (T) -> R): R

T类型调用let函数,lambda表达式作为参数,该对象为函数的参数,作用域内it指代,闭包形式返回,返回值由return表达式指定或作用域内最后一行,可用于可空对象的判空后统一处理

testInline?.let { 
    it.length
    it[1]
    it.plus("123")
}

with函数

public inline fun <T, R> with(receiver: T, block: T.() -> R): R

接收T类型对象和lambda表达式作为参数,作用域中this指代T类型对象,对象的属性为非空类型时可省略this,直接使用对象属性。闭包形式返回,返回值由return表达式指定或作用域内最后一行

val a = with(testUserDetail.value, {
    LogUtils.e("inline0315", "test with = ${this.nickname}")
    LogUtils.e("inline0315", "test with = $id")
    age
})

或者

val b = with(testUserDetail.value) {
    LogUtils.e("inline0315", "test with = ${this.nickname}")
    LogUtils.e("inline0315", "test with = $id")
    return@with age
}

Run函数

public inline fun <T, R> T.run(block: T.() -> R): R
Let函数与with函数的结合

val a = testUserDetail.value.run {
    LogUtils.e("inline0315", "test run = ${this.nickname}")
    LogUtils.e("inline0315", "test run = $id")
}

apply函数

public inline fun <T> T.apply(block: T.() -> Unit): T
结构与run函数类似,返回值是调用的对象本身

val a = testUserDetail.value.apply {
    this.nickname = "test"
    age = 20
}
LogUtils.e("inline0315", "test apply = $a")

应用场景类似于常用的链式调用

also函数

public inline fun <T> T.also(block: (T) -> Unit): T
结构与let函数类似,返回值是调用的对象本身

val a = testUserDetail.value.also {
    it.nickname = "test also"
    it.age = 21
}

与 reified 关键字使用,实化类型参数函数

inline fun <reified T: BaseViewModel>getViewModel(context: AppCompatActivity): T {
    return ViewModelProvider(context).get(T::class.java)
}

reified只能与inline使用,被reified修饰的泛型,可以作为实化类型使用,如这里的T::class.java,若没有使用reified,T不能直接被使用

扩展函数、扩展属性

一般用于给已有三方、系统等无法修改的库新增功能以满足项目需求,扩展不会修改原有代码,不会对原有功能产生影响

fun UserDetailBean.testFun() {
    LogUtils.e("extension0315", "test fun nickname = ${this.nickname}")
}

UserDetailBean 为被扩展类型(接收者类型),方法体中this为这个类的对象,即调用者,可省略,但不能访问私有属性和方法,子类可调用父类扩展方法但不能重写

var UserDetailBean.testAttribute: String?
    get() {
        return this.nickname
    }
    set(value) {
        this.nickname = value
    }

必须提供get和set方法

var UserDetailBean.testAttribute: String?
    get() {
        return this.nickname
    }
    set(value) {
        this.nickname = value
    }

fun UserDetailBean.testFun() {
    LogUtils.e("extension0315", "test fun nickname = ${this.nickname}")
}

testUserDetail.value.let {
    LogUtils.e("extension0315", "test att nickname before = ${it.nickname}")
    it.testAttribute = "test attribute"
    LogUtils.e("extension0315", "test att nickname after = ${it.nickname}")
    it.testFun()
}

extension0315: test att nickname before = null
extension0315: test att nickname after = test attribute
extension0315: test fun nickname = test attribute

高阶函数

定义:函数的参数或者返回值是函数(lambda表达式)
之前提到的操作集合的常用函数、内联函数等多是高阶函数。
注:return从最近的fun关键字返回
如函数A中调用了另一函数B,B的lambda中使用了return 且B是内联函数, 会从A函数返回,如需从B中返回需使用标签 @,若B是非内联函数不可使用return

private fun testReturn() {
    fragments.forEach {
        LogUtils.e("testReturn0317", "fragment simpleClassName = ${it.javaClass.simpleName}")
        if (it is MainFg) {
            return
        }
    }
    LogUtils.e("testReturn0317", "after return forEach")
}

testReturn0317: fragment simpleClassName = MainFg
testReturn0317: after return fun

此时return会直接从testReturn函数直接返回,若需从forEach方法中返回需使用标签 xxx@声明 return@

private fun testReturn() {
    fragments.forEach label@ {
        LogUtils.e("testReturn0317", "fragment simpleClassName = ${it.javaClass.simpleName}")
        if (it is MainFg) {
            return@label
        }
    }
    LogUtils.e("testReturn0317", "after return forEach")
}

testReturn0317: fragment simpleClassName = MainFg
testReturn0317: after return forEach
testReturn0317: after return fun

或者不声明label 直接return@forEach也可

如果使用了匿名函数,return就会从这个匿名函数返回

private fun testReturn() {
    fragments.forEach(fun(fragment) {
        LogUtils.e("testReturn0317", "fragment simpleClassName = ${fragment.javaClass.simpleName}")
        if (fragment is MainFg) {
            return
        }
    })
    LogUtils.e("testReturn0317", "after return forEach")
}

testReturn0317: fragment simpleClassName = MainFg
testReturn0317: after return forEach
testReturn0317: after return fun
如需从外层函数返回可写作return@testReturn

顶层函数

顶层函数可替代Java中使用的静态方法。Java中使用 类名.方法名 的形式来调用静态方法,Kotlin中方法可以不属于任何一个类,可以直接定义在一个kotlin文件中,使用时直接调用方法名即可,除函数外还可以定义顶层属性。Java中也可调用kotlin顶层函数,通过 文件名.方法名 的形式调用。

中缀调用

val testMap = mapOf(Pair(1, "a"), Pair(2, "b"), Pair(3, "c"))
val testMap1 = mapOf(1.to("A"), 2.to("B"), 3.to("C"))
val testMap2 = mapOf(1 to "AA", 2 to "BB", 3 to "CC")

第一种方式是常规创建Pair对象,第二种方式是调用 to 函数,第三种也是函数的调用,称为 中缀调用
public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
能被中缀调用的函数在声明时需用infix修饰

解构声明

val (key, value) = 1 to "AAA"

类似的作用可用于map的循环中

for ((key, value) in testMap) {
    LogUtils.e("testOther0317", "key = $key, value = $value")
}

testOther0317: key = 1, value = a
testOther0317: key = 2, value = b
testOther0317: key = 3, value = c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值