Kotlin 小细节记录(7)函数-高阶函数-Lambda
2022-03-03 本文已影响0人
zcwfeng
函数-高阶函数-Lambda
1. 函数调用省略
var method01:(Int)->Unit = {value -> println(value)}
fun main() {
method01(111)
method01.invoke(22222)
}
函数调用省略invoke()
直接使用 (......)
2. 函数声明与实现
: (参数)->返回
= {参数->方式}
的步理解声明和实现, 有点C++的身影
var method02 : (Int)->String // 先声明
method02 = fun(value : Int) : String= value.toString() // 后实现
println(method02(99))
// 用 先声明 的类型,来 自动推断
var method03 : (Int)->String // 先声明
method03 = fun(value) = value.toString() // 后实现
println(method03(99))
// 声明 + 实现 一气呵成
var method04 : (Int) -> String/*左边是声明*/= {value-> "$value aaa"}/*右边是实现*/
println(method04(77))
3. 函数的几种类型接收和返回参数
fun showAction(action: (Int) -> String) {
println(action(88))
}
fun lambdaImpl(value: Int) = "my value is$value"
showAction(::lambdaImpl)
val r1: Function1<Int,String> = ::lambdaImpl
val r2: (Int) -> String = ::lambdaImpl
val r3: Int.() -> String = r2
多个lambda的函数
fun lambdaMulti(lambda1:(String)->Unit,lambda2:(Int)->Unit){
......
}
--------------------------------
lambdaMulti({},{})
lambdaMulti({
}){
}
一个Lambda嵌套的有趣例子
val fan: (String) -> (String) -> (Boolean) -> (Int) -> (String) -> Int = {
{
{
{
{
99
}
}
}
}
}
println(fan("AAA")("bbb")(false)(44)("aaaa"))
模拟添加事件,lambda 没法用泛型,用any替代
class AndroidClickListener<T> {
private val actions = arrayListOf<(T?) -> Unit>()
private val valuse = arrayListOf<T?>()
fun addListener(value: T?, action: (T?) -> Unit) {
if (!actions.contains(action)) {
actions += action
valuse += value
}
}
fun touchListeners() {
if (actions.isEmpty()) {
println("not action")
return
}
actions?.forEachIndexed { index, item ->
item.invoke(valuse[index])
}
}
}
fun <T> show(value: T?) {
println("event is value:$value")
}
fun main() {
val func = AndroidClickListener<String>()
func.touchListeners()
func.addListener("zcwfeng") {
println("事件执行 ,value is $it")
}
//lambda 没法用泛型,用any替代
var result: (Any?) -> Unit = ::show
val method1: (Any) -> Unit = {}
func.touchListeners()
println()
// 我想传递 事件
func.addListener("zcwfeng", ::show)
// lambda无法玩泛型
func.touchListeners()
}
4. 函数定义
fun study01() = {
}
这句话是两个函数
看个复杂点的例子,包含一个lambda函数
fun study01() = { name:String,age:Int->
true
name
age
"name is:$name,age is: $age"
}
fun study02() = {lambdaAction:(Int,Int)->String,studyInfo:String->
false
'男'
val lambdaAction = lambdaAction(10,10)
println("lambdaAction function result is :$lambdaAction + $studyInfo")
}
fun main() {
println(study01()("zcwfeng",99))
study02()({n1,n2->
"两个num相加得到的结果:${n1 + n2}"
},"zcwfeng")
}
------------------------
来看函数的返回类型
fun study03() = { str:String,num:Int,lambda1:(String)->Unit,lambda2:(Int)->Unit ->
lambda1(str)
lambda2(num)
}
返回类型 (String,Int,(String)->Unit,(Int)->Unit) -> Unit
study03()("zcwfeng",11,{
println("lambda1 value is:$it")
}){
println("lambda2 value is:$it")
}
最后一个lambda可以写到()后面也可以卸载参数里study03()("","",{},{})或者study03()("","",{}){}
泛型化
fun <T1, T2, R1, R2> study04() = { str: T1, num: T2, lambda1: (T1) -> R1, lambda2: (T2) -> R2 ->
println("lambda1 is value ${lambda1(str)}")
println("lambda2 is value ${lambda2(num)}")
}
study04<String, Int, Int, String>()("zcwfeng", 100, {
"$it".length// 类似rx str to int
}, {
"$it to String"// int to string
})
5. 模仿RXJava 的操作符
fun main() {
create {
"zcwfeng"
}.map {
it.length
}.map {
"长度是$it"
}.map {
"[$it]"
}.compose {
println(it)
}
}
//保存map
class Helper<T>(private var item: T) {
// 链式调用
fun <R> map(lambda: (T) -> R) = Helper(item)
fun compose(action: (T) -> Unit) = action(item)
}
fun <R> create(action: () -> R) = Helper(action())
通过扩展函数简化后的代码
fun main() {
create {
"zcwfeng"
}.map {
length
}.map {
"长度是$this"
}.map {
"[$this]"
}.compose {
println(this)
}
}
//保存map
class Helper<T>(var item: T)
// 链式调用
fun <T,R> Helper<T>.map(lambda: T.() -> R) = Helper(lambda(item))
fun<T> Helper<T>.compose(action: T.() -> Unit) = action(item)
fun <R> create(action: () -> R) = Helper(action())
6. forEach 内置函数仿写
使用
listOf("aaa", "bbb", "ccc")
.forEach {
println(it)
}
println();
listOf("aaa", "bbb", "ccc")
.mForeach {
println(it)
}
----------
inline fun <T> Iterable<T>.mForeach(lambda: (T) -> Unit) = kotlin.run {for (item in this) lambda(item) }
如果Lambda中println(this)我不想用it,那么稍微改造下
inline fun <T> Iterable<T>.mForeach(lambda: T.() -> Unit) = kotlin.run {for (item in this) lambda(item) }
不用系统的run,自己实现
inline fun <T> Iterable<T>.mForeach(lambda: T.() -> Unit) = r { for (item in this) lambda(item) }
inline fun <R> r(lambda: () -> R) = lambda()
小技巧:T.() 扩展写法持有this----(T) 持有的是it
7. 仿写let内置函数
"zcwfeng".let {
'a'
0
99.99
}
"zcwfeng".mLet {
'2'
111
println("value is $it")
false
}
inline fun <T, R> T.mLet(lambda: (T) -> R): R = lambda(this)
7. 仿写repeat内置函数
repeat(10){
println("下标是$it")
}
mRepeat(10){
println("下标是$it")
}
10.mRepeat2{
print("下标是$it ")
}
private inline fun mRepeat(count:Int,lambda: (Int) -> Unit){
for (index in 0 until count) lambda(index)
}
private inline fun Int.mRepeat2(lambda: (Int) -> Unit){
for (index in 0 until this) lambda(index)
}
8. 仿写内置函数repeat
val test = "zcwfeng".takeIf {
true
false
}
println(test)
val test1 = "zcwfeng".mTakeIf {
true
false
}
println(test1)
private inline fun <T> T.mTakeIf(lambda: (T) -> Boolean): T? = if (lambda(this)) this else null
9 . 仿写内部thread函数
thread {
println("thread")
}
mThread(/*name = "dddd"*/) {
println("mThread ${Thread.currentThread().name}")
}
private inline fun mThread(
start: Boolean = true,
name: String? = null,
crossinline runAction: () -> Unit
) {
val thread = object : Thread() {
override fun run() {
super.run()
runAction()
}
}
if (start) thread.start()
name?.let { thread.name = name }
}
crossinline 声明是防止inline的发生,防止代码错误