Function lambda分配给Kotlin中的变量。为什么?
我注意到,如果我定义这个平凡的函数,我会得到同样的效果:Function lambda分配给Kotlin中的变量。为什么?,function,variables,lambda,kotlin,Function,Variables,Lambda,Kotlin,我注意到,如果我定义这个平凡的函数,我会得到同样的效果: fun double ( i: Int ) = i*2 如果我定义了一个变量并给它分配了一个lambda(具有相同的主体): 如果使用两种声明调用double(a),则得到相同的结果。 这让我感到困惑。当需要时,建议将变量定义为lambda而不是为其定义函数,这样做比较有利?当您出于某种原因想要更改行为时,可以定义变量并将其分配为lambda。例如,对于几种情况,您有不同的公式 val formula: (Int) -> Int
fun double ( i: Int ) = i*2
如果我定义了一个变量并给它分配了一个lambda(具有相同的主体):
如果使用两种声明调用double(a)
,则得到相同的结果。
这让我感到困惑。当需要时,建议将变量定义为lambda而不是为其定义函数,这样做比较有利?当您出于某种原因想要更改行为时,可以定义变量并将其分配为lambda。例如,对于几种情况,您有不同的公式
val formula: (Int) -> Int = when(value) {
CONDITION1 -> { it*2 }
CONDITION2 -> { it*3 }
else -> { it }
}
val x: Int = TODO()
val result = formula(x)
如果您只是需要helper函数,您应该首先将其定义为
fun
,如果我没弄错的话,您的问题是“为什么函数是Kotlin的头等公民——以及何时使用它们?”,对吗
Kotlin函数是一级函数,这意味着它们可以存储在变量和数据结构中,作为参数传递给其他高阶函数并从中返回。您可以以其他非函数值可能的任何方式操作函数。()
如文档中所述,一个用例是高阶函数。作为第一步,我将把维基百科链接留在这里: 基本上是一个高阶函数。 这意味着高阶函数至少有一个函数类型的参数或返回函数类型的值 下面是接收函数类型为
(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")
}
//此示例故意冗长;)
变量检查器:(Int)->布尔值
如果(阳性检查){
checker={x->x>0}//存储此函数。。。
}否则{
棋盘格={x->x<0}/…或此棋盘格。。。
}
if(checker(someNumber)){//…并使用现在存储在变量“checker”中的任何函数
打印(“支票没问题”)
}
(代码未经测试)
什么时候需要(建议)将变量定义为lambda而不是为其定义函数
无论何时您可以选择其中一种,都应该使用fun
声明。即使使用fun
,您仍然可以通过使用函数引用从中获取一流的可调用对象
在JVM上,fun
在RAM和调用开销方面都要轻得多。它编译成一个Java方法,而val
编译成一个实例字段+getter+一个实现函数接口的合成类+一个必须获取、取消引用和调用该类上的方法的该类的单例实例
<>你应该考虑函数类型<代码> Val<代码> >或代码> var >代码>只有当某个东西强迫你去做它时。例如,您可以动态替换var
,并有效地更改函数的定义。您也可以从外部接收函数对象,或者您可能需要遵守需要它们的API
在任何情况下,如果您使用类的函数类型属性,您都会知道为什么要这样做。如果您将lambda作为函数的参数传递,它将存储在变量中。调用应用程序可能需要保存该文件(例如,事件侦听器以供以后使用)。因此,您还需要能够将其存储为变量。然而,正如回答中所说,您应该只在需要时才这样做 对于我来说,我将按如下方式编写Lambda变量:
var double: (Int) -> Int = { i -> //no need to specify parameter name in () but in {}
i*2
}
这样您就可以很容易地知道它的类型是(i:Int)->Int
,读作接受一个整数并返回一个整数
然后你可以把它传递到某个地方,比如说一个函数:
fun doSomething(double: (Int) -> Int) {
double(i)
}
在你提到的情况下,我认为最明显的区别是,你可以给lambda任何体,但是你不能改变函数的体。这基本上是一个什么是lambda的问题,不是吗?我不明白你的问题。你在比较一个函数和一个变量。显然,它们都有各自的用途。其中一个用途是在内联函数中使用它们。他的var-double和fun-double在幕后是否完全相同?是否只是语法将它们区分开来?@Adam:不,一般来说,afun
更轻量级。(另见@Marko Topolnik的答案)。只是一个简单的解释:aval
或var
是堆上的一个对象,即占用内存,函数类型的变量也是如此。Afun
是一个函数,是存储在JVM内部的类描述的一部分。谢谢。我正在学习关于Udacity的“Kotlin训练营”课程,它提出了这个例子,但没有真正进入这些“细节”。非常有用。回答得很好,信息量很大!你从哪里得到这个信息的?你读过类似的书吗?还是你自己检查字节码?我一直对如何用不同的语言了解东西是如何工作的感兴趣@MarkusWeninger这是熟悉Kotlin属性语义和使用内置“ShowKotlin字节码”功能的结合。
fun doSomething(double: (Int) -> Int) {
double(i)
}