如何解析具有相同名称的Kotlin函数/属性有效?

TWi*_*Rob 5 language-design kotlin

以下语句编译并打印"fun: called":

fun main(vararg args: String) {
    fun toCall(arg: String) = println("fun: $arg")
    val toCall = fun(arg: String) = println("val: $arg")
    toCall("called")
}
Run Code Online (Sandbox Code Playgroud)

注意:如果它们是顶级声明或类内部会出现同样的问题,这只是带有本地函数/变量的最简单的repro.

寻找澄清为什么这首先编译?
什么规则发挥作用,选择财产的功能?

注意:可以val通过以下方式呼叫:

  • (toCall)("called")
  • toCall.invoke("called")

Rol*_*and 1

本有关名称解析的文档包含有关它的详细信息。

\n\n

我将引用其中专门处理您的问题的一些段落。它还包含其他一些有趣的内容,但我想我最终会复制这里的所有内容;-) 如果您有兴趣,我只能建议您完整地阅读它。

\n\n

总而言之,编译器将函数(成员/扩展/成员扩展)/属性分成组,并决定先调用哪一个...属性被放入函数组中invoke,在下面的段落中,您已经明白为什么函数是在您之前执行的val

\n\n
\n

该属性与功能一起考虑invoke。具有函数的属性组与invoke常规函数组混合在一起,从某种意义上说,一组属性可以比一组函数具有更高的优先级,反之亦然。然而,函数和属性不能归为一组:函数总是超越同一类别的属性。属性和invoke函数都决定了组的优先级:我们比较属性和函数的优先级invoke,“最低”的优先级成为组优先级。

\n
\n\n

这就是为什么这里首先考虑函数,然后考虑属性的原因。一旦您指定,invoke很明显它只能是属性,因为函数本身不可见invoke(现在不要深入字节代码;-))。现在的(toCall)行为类似。这里很清楚,那toCall只能是财产。无法使用(toCall)该函数进行调用(编译错误:需要函数调用/invoke未找到该函数)。

\n\n

链接的文档还包含一个带有成员属性函数的示例,后跟此语句,这基本上也证实了前面关于局部函数的内容:

\n\n
\n

请注意,没有名为 foo 的成员函数,但如果存在,它将被放入具有最高优先级的单独组中。

\n
\n