kotlin匿名函数

匿名函数

定义

定义时不取名字的函数,我们称之为匿名函数.

我们将把匿名函数改称为 lambda,将它的定义改称为 lambda表达式,它的返回数据改称为 lambda 结果。

匿名函数通常整体传递给其他函数,或者从其他函数返回。

  • 定义一个匿名函数
fun main(args: Array<String>) { 
    println({ 
        val currentYear = 2018 
        "Welcome to SimVillage, Mayor! (copyright $currentYear)" 
    }()) 
}

定义字符串就是把字符放在一对引号中间。类似地,定义函数就是把表达式或语句放在一对花括号里。这里,你首先调用 println 函数。在一对花括号里定义一个匿名函数,将其放在println 函数的参数圆括号里。匿名函数里定义了一个变量,返回一条欢迎字符串信息。

{ 
    val currentYear = 2018 
    "Welcome to SimVillage, Mayor! (copyright $currentYear)" 
}

我们在花括号的后面跟上一对空的圆括号,表示调用匿名函数。圆括号不能省,否则就不会输出欢迎信息。和具名函数一样,要让匿名函数工作,就得调用它,并在参数圆括号里传入对应的值参(没参数就空着):

{ 
    val currentYear = 2018 
    "Welcome to SimVillage, Mayor! (copyright $currentYear)" 
}()

函数类型

定义一个存储函数的变量,把输出欢迎语句的匿名函数赋给它。

  • 把匿名函数赋值给变量
fun main(args:Array<String>) {
    val helloFunction : () -> String = {

        "hello world"
    }
    println(helloFunction())
}
定义变量时,是在变量名后面跟上冒号和类型。greetingFunction: () -> String 代码片段也是这样做的。
对编译器来讲,: Int 表示变量存储的是哪种类型的数据(整数),: () -> String 表示变量存储的是哪种类型的函数。

函数类型定义包括两个部分,它们以箭头符号隔开:一对圆括号里面的函数参数和紧跟着的返回数据类型。

fun helloFunction() : String
				|     |
			    () -> String
() -> String 是你给 helloFunction 变量指定的函数类型定义,它告诉编译器,任何不需要参数(以圆空括号表示)、能返回 String 的函数,都可以赋给greetingFunction 变量。
和变量的类型定义一样,无论匿名函数是赋给 helloFunction 变量,还是作为值参传递,
编译器都会进行检查以确保它的类型满足要求。

隐式返回

val greetingFunction: () -> String = { 
    val currentYear = 2018 
    "Welcome to SimVillage, Mayor! (copyright $currentYear)" 
}

匿名函数不需要 return 关键字来返回数据。没有 return 关键字,为了返回数据,匿名函数会隐式或自动返回函数体最后一行语句的结果。

这个特性不仅很方便,也是匿名函数语法的特别要求。之所以不能用 return 关键字,是因为编译器不知道返回数据究竟是来自调用匿名函数的函数,还是匿名函数本身。

带有函数参数

匿名函数需要带参数时,参数的类型放在匿名函数的类型定义中,参数名则放在函数定义中。

fun main(args:Array<String>) {

    val helloFunction : (String) -> String = { name ->
                                              "hello world" + name
                                             }

    println(helloFunction("naruto"))
}

现在匿名函数有了一个 String 类型的参数。具体的写法如下:在匿名函数体内,左花括号的后面,写上 String 类型的参数名,后面再跟上一个箭头符号。

val greetingFunction: (String) -> String = { playerName -> 

it 关键字

定义只有一个参数的匿名函数时,可以使用 it 关键字来表示参数名。当你有一个只有一个参数的匿名函数时,it 和命名参数都有效.

fun main(args:Array<String>) {
    val itFunction : (String) -> (String) = {
        "$it"+"hhhh"
    }
    println(itFunction("hello"))
}

多个参数

如果有多个参数,需要使用命名参数。

fun main(args:Array<String>) {

    val itFunction : (String,String) -> (String) = {param1,param2->

        param1 + "---->" + param2
    }

    println(itFunction("hello","world"))
}


类型推断

Kotlin 的类型推断规则同样也适用函数类型:定义一个变量时,如果已把匿名函数作为变量值赋给它,就不需要显式指明变量类型了.

  • 不带参数的匿名函数
val greetingFunction: () -> String = { 
    val currentYear = 2018 
    "Welcome to SimVillage, Mayor! (copyright $currentYear)" 
}

类型推断

val greetingFunction = { 
    val currentYear = 2018 
    "Welcome to SimVillage, Mayor! (copyright $currentYear)" 
}
  • 带参数的匿名函数,但为了帮助编译器更准确地推断变量类型,匿名函数的参数名和参数类型必须有
fun main(args:Array<String>) {

    val itFunction : (String,String) -> (String) = {param1,param2->

        param1 + "---->" + param2
    }

    println(itFunction("hello","world"))
}

类型推断

fun main(args:Array<String>) {

    val itFunction = {param1 : String,param2:String ->

        param1 + "---->" + param2
    }

    println(itFunction("hello","world"))
}

定义参数是函数的函数

一个函数类型的参数定义起来和其他类型的参数一样:在函数名后的一对圆括号内列出,再加上类型。

fun main(args: Array<String>) {
    val greetingFunction = { playerName: String, numBuildings: Int ->
        val currentYear = 2018
        println("Adding $numBuildings houses")
        "Welcome to SimVillage, $playerName! (copyright $currentYear)"
    }
    runSimulation("Guyal", greetingFunction)
}
fun runSimulation(playerName: String, greetingFunction: (String, Int) -> String) {
    val numBuildings = (1..3).shuffled().last() // Randomly selects 1, 2, or 3
    println(greetingFunction(playerName, numBuildings))
}

runSimulation 函数有两个参数,一个是玩家的名字,一个是 greetingFunction。其中,greetingFunction 也是一个函数,它也有两个参数,一个 String 类型和一个 Int 类型,它返回 String 类型的数据。

简略语法

在 Kotlin 中,可以使用简略语法传入 Lambda 表达式作为函数的参数。如果函数的最后一个参数是一个 Lambda 表达式,那么可以将该表达式写在调用括号外面,并使用大括号 {} 包裹起来,从而省略掉部分冗余的语法。这种简略语法可以使代码更加简洁易读。

// 定义函数类型的参数
fun performRequest(url: String, callback: (String) -> Unit) {
    // 执行请求操作...
    val response = "Response from $url"
    // 调用回调函数
    callback(response)
}

// 使用简略语法传入 Lambda 表达式作为参数
performRequest("https://my.api.com") { response ->
    println(response)
}

在这个例子中,我们定义了一个名为 performRequest 的函数,它接受一个字符串类型的 URL 和一个函数类型的参数 callback,该参数表示请求完成后的回调函数。在函数体内,我们模拟了一个请求操作,并生成了一个响应字符串。接着,我们调用了回调函数,并传递了该响应字符串作为参数。

在函数调用时,我们使用了简略语法,将 Lambda 表达式写在了调用括号外面,并使用大括号 {} 包裹起来。Lambda 表达式接受一个字符串参数 response,并在函数体内打印了该参数的值。

需要注意的是,使用简略语法时,只有当 Lambda 表达式是函数的最后一个参数时才能省略掉部分冗余的语法,否则需要显式地指定参数名称和类型。

函数类型作为返回类型

和其他数据类型一样,函数类型也是有效的返回类型,也就是说,你可以定义一个能返回函数的函数。

fun main(args: Array<String>) {

    runSimulation()
}

fun runSimulation() {
    val greetingFunction = configureGreetingFunction()
    println(greetingFunction("Guyal"))
}

fun configureGreetingFunction(): (String) -> String {
    val structureType = "hospitals"
    var numBuildings = 5
    return { playerName: String ->
        val currentYear = 2018
        numBuildings += 1
        println("Adding $numBuildings $structureType")
        "Welcome to SimVillage, $playerName! (copyright $currentYear)"
    }
}

posted @ 2023-03-15 08:16  传说中的旅行者  阅读(165)  评论(0编辑  收藏  举报