扩展函数可以用"static"的方式调用吗?

Can extension functions be called in a "static" way?

是否可以创建一个扩展函数并像静态函数一样调用它

例如...

fun System.sayByeAndExit() {
    println("Goodbye!")
    System.exit()
}

fun main(args: Array<String>) {
    System.sayByeAndExit() // I'd like to be able to call this
}

我知道代码示例不起作用...

我为什么要这个?

有些人可能想知道为什么需要这种行为。我能理解为什么你会认为那不是,所以这里有一些原因:

  1. 它具有标准扩展函数的所有优点。
  2. 不需要创建 class 的实例 只需 即可访问额外的功能。
  3. 可以从应用程序范围的上下文访问函数(前提是class可见)。

总结一下...

Kotlin 有办法将静态函数 "hook" 放到 class 上吗? 我很想知道。

您可以为 object 定义扩展函数并从系统范围的上下文中使用它。一个对象只会被创建一次。

object MyClz

fun MyClz.exit() = System.exit(0)

fun main(args: Array<String>) {
    MyClz.exit()
}

class MyClz {
    companion object
}

fun MyClz.Companion.exit() = System.exit(0)

fun main(args: Array<String>) {
    MyClz.exit()
}

你真的是在问 "extension functions for a Class reference" 或 "adding static methods to existing classes",这里有另一个问题: which is covered by a feature request KT-11968

扩展函数不能添加到没有实例的任何东西。对 Class 的引用不是一个实例,因此你不能扩展像 java.lang.System 这样的东西。但是,您可以 extend a companion object 现有 class。例如:

class LibraryThing {
    companion object { /* ... */ }
}

允许您扩展 LibraryThing.Companion 并因此调用一些新的 myExtension() 方法看起来您正在扩展 Class 引用本身,而实际上您正在扩展伴随对象:

fun LibraryThing.Companion.myExtension() = "foo"

LibraryThing.Companion.myExtension() // results in "foo"
LibraryThing.myExtension() // results in "foo"

因此,您可能会发现一些 Kotlin 库专门针对这种情况添加了空的伴随对象。其他人没有,对于那些你是 "out of luck." 因为 Java 没有伴随对象,你也不能对 Java 做同样的事情。

另一个通常要求的功能是采用现有的 Java 静态方法,该方法接受 class 的实例作为第一个参数,并使其表现为扩展函数。这是由问题 KT-5261, KT-2844, KT-732, KT-3487 和可能的其他功能请求跟踪的。