6

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

例如...

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

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

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

  • 我知道 kotlin 的扩展函数是静态解析的,Kotlin Reference (Extension Functions)中所述,但这并不意味着它们可以像类中的静态函数一样被调用(在 Java 意义上)。

  • 我也知道这段代码不起作用,因为没有 System 实例可以传递给编译器将生成的方法;因此它不会编译。

我为什么要这个?

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

  1. 它具有标准扩展功能提供的所有好处。
  2. 不需要创建类 实例来访问额外的功能。
  3. 可以从应用程序范围的上下文中访问这些函数(假设类是可见的)。

总结...

Kotlin 有办法将静态函数“挂钩”到类上吗?我很想知道。

4

2 回答 2

10

您实际上是在要求“类引用的扩展函数”或“向现有类添加静态方法”,此处的另一个问题已涵盖:如何将静态方法添加到 Kotlin中的 Java 类,该功能请求KT- 11968

扩展函数不能添加到没有实例的任何东西上。对 Class 的引用不是实例,因此您不能扩展类似java.lang.System. 但是,您可以扩展现有类的伴随对象。例如:

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 库仅针对这种情况添加了空的伴随对象。其他人没有,而对于那些你“不走运”。由于 Java 没有伴生对象,因此您也不能对 Java 做同样的事情。

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

于 2016-09-04T01:13:52.820 回答
1

您可以为 an 定义扩展函数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()
}
于 2016-09-03T18:41:27.190 回答