Kotlin函数声明:在花括号之前等于符号

hot*_*key 24 function kotlin

在Kotlin中,函数声明语法允许您在花括号之前写入等号.考虑这两个例子:

  1. 没有=标志:

    fun foo() {
        bar()
        println("baz")
    }
    
    Run Code Online (Sandbox Code Playgroud)

    只需调用即可执行正文中的代码foo().

  2. =标志:

    fun foo() = {
        bar()
        println("baz")
    }
    
    Run Code Online (Sandbox Code Playgroud)

    在这里,当foo()被调用时,没有任何事情发生,但为了让身体执行,可以写foo()().

这两个声明有什么不同,为什么它们的表现不同?


这个问题尽管没有多大意义,但是作者有意提问并回答,因为已经发布了一些问题,因为功能定义不正确导致人们遇到问题.

hot*_*key 31

尽管视觉上相似,但这两个声明的想法完全不同.

  1. 没有等号的函数声明是一个Unit返回函数(类似于Java的void函数).

    花括号里面的是它的主体,它在函数调用时被执行.可以使用Unit显式指定重写该函数:

    fun foo(): Unit {
        bar()
        println("baz")
        return Unit
    }
    
    Run Code Online (Sandbox Code Playgroud)

    Kotlin对Unit-returning函数不需要return语句和显式返回类型,两者通常都省略.

  2. 具有等号的函数声明是单表达式函数,它所做的只是返回等号右边的内容.

    一个更简单的例子:fun getInt() = 1只是一种较短的形式fun getInt(): Int { return 1 }.

    foo,表达式是一个lambda,它只返回,而不是执行.

    返回类型foo() -> Unit一个函数本身,因此foo是一个高阶函数.

    如果没有语法糖和显式类型,foo可以重写为

    fun foo(): () -> Unit {
        val result: () -> Unit = { bar(); println("baz") }
        return result
    }
    
    Run Code Online (Sandbox Code Playgroud)

    至于用法,foo返回的函数可以存储在变量中,传递并稍后可以调用:

    val f = foo()
    
    f() //equivalent to
    f.invoke()
    
    Run Code Online (Sandbox Code Playgroud)

    这也是为什么foo()()在示例中执行lambda主体的代码的原因.