【Kotlin -- 知识点】高阶函数

一、什么是高阶函数

在 Kotlin 中,高阶函数即指:将函数用作一个函数的参数或者返回值的函数。

1. 将函数用作函数参数的情况的高阶函数

sumBy{} 高阶函数源码:

// sumBy函数的源码
public inline fun CharSequence.sumBy(selector: (Char) -> Int): Int {
    
        
	var sum: Int = 0    
	for (element in this) {
    
            
		sum += selector(element)    
	}    
	return sum
}

解释说明:

  • 该函数返回一个 Int 类型的值。并且接受了一个 selector() 函数作为该函数的参数。其中,selector() 函数接受一个 Char 类型的参数,并且返回一个Int类型的值。
  • 定义一个 sum 变量,并且循环这个字符串,循环一次调用一次 selector() 函数并加上 sum。用作累加。其中 this 关键字代表字符串本身。

这个函数的作用是:把字符串中的每一个字符转换为 Int 的值,用于累加,最后返回累加的值。

例子:

val testStr = "abc"
val sum = testStr.sumBy {
    
     it.toInt() }
println(sum)

输出结果:

294 // 因为字符a对应的值为97,b对应98,c对应99,故而该值即为 97 + 98 + 99 = 294

2. 将函数用作一个函数的返回值的高阶函数

lock() 函数源码:

fun <T> lock(lock: Lock, body: () -> T): T {
    
    
    lock.lock()
    try {
    
    
        return body()
    }
    finally {
    
    
        lock.unlock()
    }
}

解释说明:

  • 从源码可以看出,该函数接受一个 Lock 类型的变量作为参数 1,并且接受一个无参且返回类型为 T 的函数作为参数 2.
  • 该函数的返回值为一个函数,我们可以看这一句代码 return body() 可以看出。

例子:

fun toBeSynchronized() = sharedResource.operation()
val result = lock(lock, ::toBeSynchronized) 

3. 高阶函数的使用

这里主要讲高阶函数中对 Lambda 语法的简写:

str.sumBy( {
    
     it.toInt } )

根据 Kotlin 中的约定,即当函数中只有一个函数作为参数,并且您使用了 lambda 表达式作为相应的参数,则可以省略函数的小括号()。

str.sumBy{
    
     it.toInt }

当函数的最后一个参数是一个函数,并且你传递一个lambda表达式作为相应的参数,则可以在圆括号之外指定它。

val result = lock(lock){
    
    
    sharedResource.operation()
}

二、自定义高阶函数

例子:传入两个参数,并传入一个函数来实现加减乘除。

private fun resultByOpt(num1 : Int , num2 : Int , result : (Int ,Int) -> Int) : Int{
    
    
    return result(num1,num2)
}

fun main() {
    
    
    val result1 = resultByOpt(1,2){
    
    
        num1, num2 ->  num1 + num2
    }

	val result2 = resultByOpt(3,4){
    
    
        num1, num2 ->  num1 - num2
    }

	val result3 = resultByOpt(5,6){
    
    
        num1, num2 ->  num1 * num2
    }

	val result4 = resultByOpt(6,3){
    
    
        num1, num2 ->  num1 / num2
    }

	println("result1 = $result1")    
	println("result2 = $result2")    
	println("result3 = $result3")    
	println("result4 = $result4")
}

输出结果:

result1 = 3
result2 = -1
result3 = 30
result4 = 2

三、常用高阶函数

1. TODO函数

这个函数不是一个高阶函数,它只是一个抛出异常以及测试错误的一个普通函数。

作用:显示抛出 NotImplementedError 错误。NotImplementedError 错误类继承至 Java 中的
Error

例子:

fun main(args: Array<String>) {
    
    
    TODO("测试TODO函数,是否显示抛出错误")
}

输出结果:
在这里插入图片描述
如果调用 TODO() 时,不传参数的,则会输出 An operation is not implemented.

2. run 函数

run 函数这里分为两种情况讲解,采用不同的 run 函数会有不同的效果。

  • run()
    当我们需要执行一个代码块的时候就可以用到这个函数,并且这个代码块是独立的。即我可以在 run() 函数中写一些和项目无关的代码,因为它不会影响项目的正常运行。

例子:

private fun testRun1() {
    
    
    val str = "kotlin"

	run{
    
    
        val str = "java"   // 和上面的变量不会冲突
        println("str = $str")
    }
	
	println("str = $str")
}

输出结果:

str = java
str = kotlin

  • T.run()
    当我们传入的 lambda 表达式想要使用当前对象的上下文的时候,我们可以使用这个函数。

例子:

val str = "kotlin"
str.run {
    
        
	println( "length = ${
      
      this.length}" )    
	println( "first = ${
      
      first()}")    
	println( "last = ${
      
      last()}" )
}

输出结果:

length = 6
first = k
last = n

3. with()函数

with() 函数和 T.run() 函数的作用是相同的,这两个函数的区别在于:

  • with 是正常的高阶函数,T.run() 是扩展的高阶函数。
  • with函数的返回值指定了 receiver 为接收者。

例子:

val str = "kotlin"
with(str){
    
        
	println( "length = ${
      
      this.length}" )    
	println( "first = ${
      
      first()}")    
	println( "last = ${
      
      last()}" )
}

输出结果:

length = 6
first = k
last = n

4. T.apply()函数

从 T.apply() 源码中在结合前面提到的 T.run() 函数的源码我们可以得出,这两个函数的逻辑差不多,唯一的区别是T,apply 执行完了 block() 函数后,返回了自身对象。

例子:为TextView设置属性后,再设置点击事件

val mTvBtn = findViewById<TextView>(R.id.text)
mTvBtn.apply{
    
    
    text = "kotlin"
    textSize = 13f
    ...
}.apply{
    
    
    // 这里可以继续去设置属性或一些TextView的其他一些操作
}.apply{
    
    
    setOnClickListener{
    
     .... }
}

或者:设置为 Fragment 设置数据传递

// 原始方法
fun newInstance(id : Int , name : String , age : Int) : MimeFragment{
    
            
	val fragment = MimeFragment()        
	fragment.arguments?.putInt("id",id)        
	fragment.arguments?.putString("name",name)        
	fragment.arguments?.putInt("age",age)        

	return fragment
}

// 改进方法
fun newInstance(id : Int , name : String , age : Int) = MimeFragment().apply {
    
            
	arguments = Bundle()        
	arguments?.putInt("id",id)        
	arguments?.putString("name",name)        
	arguments?.putInt("age",age)
}

5. T.also()函数

T.also 函数中的参数 block 函数传入了自身对象。故而这个函数的作用是用 block 函数调用自身对象,最后在返回自身对象。

例子:

"kotlin".also {
    
    
    println("结果:${
      
      it.plus("-java")}")
}.also {
    
    
    println("结果:${
      
      it.plus("-php")}")
}

"kotlin".apply {
    
    
    println("结果:${
      
      this.plus("-java")}")
}.apply {
    
    
    println("结果:${
      
      this.plus("-php")}")
}

输出结果:

结果:kotlin-java
结果:kotlin-php
结果:kotlin-java
结果:kotlin-php

6. T.let()函数

T.let 的作用也不仅仅在使用空安全这一个点上。用 T.let 也可实现其他操作

例子:

"kotlin".let {
    
    
    println("原字符串:$it")         // kotlin
    it.reversed()
}.let {
    
    
    println("反转字符串后的值:$it")     // niltok
    it.plus("-java")
}.let {
    
    
    println("新的字符串:$it")          // niltok-java
}

"kotlin".also {
    
    
    println("原字符串:$it")     // kotlin
    it.reversed()
}.also {
    
    
    println("反转字符串后的值:$it")     // kotlin
    it.plus("-java")
}.also {
    
    
    println("新的字符串:$it")        // kotlin
}

"kotlin".apply {
    
    
    println("原字符串:$this")     // kotlin
    this.reversed()
}.apply {
    
    
    println("反转字符串后的值:$this")     // kotlin
    this.plus("-java")
}.apply {
    
    
    println("新的字符串:$this")        // kotlin
}

输出结果:

原字符串:kotlin
反转字符串后的值:niltok
新的字符串:niltok-java
原字符串:kotlin
反转字符串后的值:kotlin
新的字符串:kotlin
原字符串:kotlin
反转字符串后的值:kotlin
新的字符串:kotlin

7. T.takeIf()函数

这个函数的作用是:传入一个你希望的一个条件,如果对象符合你的条件则返回自身,反之,则返回null

例子:

val str = "kotlin"

val result = str.takeIf {
    
    
    it.startsWith("ko") 
}

println("result = $result")

输出结果:

result = kotlin

8. T.takeUnless()函数

这个函数的作用和T.takeIf()函数的作用是一样的。只是和其的逻辑是相反的。

例子:

val str = "kotlin"

val result = str.takeUnless {
    
    
    it.startsWith("ko") 
}

println("result = $result")

输出结果:

result = null

9. repeat()函数

这个函数的作用是:根据传入的重复次数去重复执行一个我们想要的动作(函数)

例子:

repeat(5){
    
     println("我是重复的第${
      
      it + 1}次,我的索引为:$it") }

输出结果:

我是重复的第1次,我的索引为:0
我是重复的第2次,我的索引为:1
我是重复的第3次,我的索引为:2
我是重复的第4次,我的索引为:3
我是重复的第5次,我的索引为:4

10. lazy()函数

关于Lazy()函数来说,它共实现了4个重载函数,都是用于延迟操作,不过这里不多做介绍。

猜你喜欢

转载自blog.csdn.net/duoduo_11011/article/details/125651643
今日推荐