从概念上讲,它们是不同的东西。为了看到这一点,让我们大致看一下等效的 Java 是什么。我将在此答案中使用 JVM 作为示例,但相同的原则适用于所有其他 Kotlin 后端。
object Foo {
fun main() { ... }
}
大概是这样
class Foo {
public static void main() { ... }
}
再次,大致。从技术上讲,除非您使用@JvmStatic,否则您将获得一个单例对象和一个方法(我假设main 有一些特殊处理会在JVM 上产生一个静态函数,但我不知道这是事实)
另一方面,
object Foo {
val main: () -> Unit = { ... }
}
在这里,我们声明了一个属性,在 Java 中将实现为 getter-setter 对
class Foo {
// Singleton instance
public static Foo instance = new Foo();
public Supplier<Void> main;
Foo() {
main = new Supplier<Void>() {
Void get() {
...
}
}
}
}
也就是说,实际上没有main 方法。有一个main 字段,在某处深处,其中有一个函数。在我上面的示例中,该函数称为get。在 Kotlin 中,它被称为 invoke。
我喜欢这样想。 Kotlin 中的方法(即您在指定其行为的对象上定义的东西)本身并不是一流的对象。他们是存在于 对象上的二等公民。您可以通过将它们转换为函数来将它们转换为一流的对象。函数是普通对象,就像其他任何对象一样。如果你使用一个普通的对象,它可能是一个函数,也可能不是一个函数,并用() 调用它,那么你实际上是在调用.invoke(...) 方法。也就是说,() 是真正最终调用方法的对象的运算符。所以在 Kotlin 中,函数实际上只是带有自定义 invoke 和大量语法糖的对象。
您的val 定义了一个作为函数的字段。您的 fun 定义了一个方法。这两个都可以用()调用,但只有一个是真正的方法调用;另一个在另一个对象上偷偷调用.invoke。它们在语法上看起来相同的事实是无关紧要的。
俗话说,功能是穷人的对象,对象是穷人的功能。