在Kotlin中分配给变量的Lambda。为什么?

时间:2018-10-17 07:49:19

标签: function variables lambda kotlin

我注意到,如果定义这个琐碎的函数,我会得到相同的效果:

12

如果我定义一个变量并为其分配一个lambda(具有相同的主体):

fun double ( i: Int ) = i*2

如果我用任一声明调用var double = { i : Int -> i*2 } ,我将得到相同的结果。 这让我感到困惑。建议何时需要将变量定义为lambda而不是为其定义函数,这是有利的?

5 个答案:

答案 0 :(得分:6)

  

建议何时需要将变量定义为lambda而不是为其定义函数是有利的?

无论何时选择,都应使用fun声明。即使使用fun,您仍然可以通过使用函数引用从中获得一流的可调用对象。

在JVM上,无论是在RAM还是在调用开销方面,fun的重量都明显更轻。它编译成Java方法,而val编译成实例字段+ getter +实现功能接口的综合类+该类的单例实例,您必须在其上获取,解引用和调用方法

仅当某些事情迫使您这样做时,才应考虑使用函数类型的valvar。一个示例是您可以动态替换var并有效地更改函数的定义。您可能还会从外部接收功能对象,或者可能需要遵循需要它们的API。

无论如何,如果您曾经使用一个类的函数类型的属性,您就会知道为什么要这么做。

答案 1 :(得分:4)

首先,如果我理解正确,您的问题是:“为什么Kotlin中的功能一等公民?为什么要这样使用它们?”,对吗?

  

Kotlin函数是一流的,这意味着它们可以存储在变量和数据结构中,作为参数传递给其他高阶函数并从其他高阶函数返回。您可以通过其他非函数值可能使用的任何方式来使用函数。 (see here


如文档中所述,一个用例是高阶函数。第一步,我将在此处保留Wikipedia链接:https://en.wikipedia.org/wiki/Higher-order_function

基本上是高阶函数is a function that takes functions as parameters, or returns a function。 这意味着高阶函数至少具有一个 function type 参数或返回一个 function type 值。

下面是接收函数类型为(Int) -> Boolean的参数的高阶函数的简短示例:

fun foo(pred: (Int) -> Boolean) : String = if(pred(x)) "SUCCESS" else "FAIL"

现在可以使用任何(Int) -> Boolean函数来调用此高阶函数。


文档还声明 ... [可以用于]其他非功能值

例如,这意味着您可以根据当前上下文为变量分配不同的功能。

例如:

// This example is verbose on purpose ;)
var checker: (Int) -> Boolean
if (POSITIVE_CHECK) {
    checker = { x -> x > 0 } // Either store this function ...
} else {
    checker = { x -> x < 0 } // ... or this one ...
}
if (checker(someNumber)) { // ... and use whatever function is now stored in variable "checker" here
  print("Check was fine")
}

(未经测试的代码)

答案 2 :(得分:2)

由于某些原因想要更改行为时,可以定义变量并将其分配为lambda。例如,在几种情况下,您有不同的公式。

val formula: (Int) -> Int = when(value) {
    CONDITION1 -> { it*2 }
    CONDITION2 -> { it*3 }
    else -> { it }
}
val x: Int = TODO() 
val result = formula(x)

如果仅需要帮助程序功能,则应将其定义为fun

答案 3 :(得分:1)

如果将lambda作为函数的参数传递,它将存储在变量中。调用应用程序可能需要保存该内容(例如事件监听器,以备后用)。因此,您还需要能够将其存储为变量。如答案中所述,仅应在需要时执行此操作!

答案 4 :(得分:0)

对我来说,我会按如下方式编写 Lambda 变量:

var double: (Int) -> Int = { i ->    //no need to specify parameter name in () but in {}
    i*2 
}

这样你就可以很容易地知道它的类型是(i: Int) -> Int,读作takes an integer and returns an integer

然后你可以把它传递给某个地方,比如一个函数:

fun doSomething(double: (Int) -> Int) {
    double(i)
}