关于kotlin:可以以“静态”方式调用扩展功能吗?

Can extension functions be called in a “static” way?

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

例如...

1
2
3
4
5
6
7
8
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参考(扩展函数)中所述,但这并不意味着它们可以像在类中的静态函数一样被调用(在Java方面)。

  • 我也理解该代码将不起作用,因为没有System实例可传递到编译器将生成的方法中。因此它不会编译。

我为什么要这个?

你们中有些人可能想知道为什么这种行为是理想的。我能理解您为什么会认为并非如此,因此有一些原因:

  • 它具有标准扩展功能提供的所有优点。
  • 无需仅为访问附加功能而创建类的实例。
  • 可以从应用程序范围的上下文访问这些功能(前提是该类可见)。
  • 总结一下...

    Kotlin是否有办法将静态函数"钩"到类上?我很想知道。


    您实际上是在要求"为类引用提供扩展功能"或"向现有类添加静态方法",这是另一个问题所涉及的:如何在功能请求KT-涵盖的Kotlin中向Java类添加静态方法? 11968

    扩展功能不能添加到没有实例的任何事物中。对类的引用不是实例,因此不能扩展java.lang.System之类的内容。但是,您可以扩展现有类的伴随对象。例如:

    1
    2
    3
    class LibraryThing {
        companion object { /* ... */ }
    }

    允许您扩展LibraryThing.Companion,因此,当您实际上在扩展伴随对象的单例实例时,调用某些新的myExtension()方法看起来就像是在扩展类引用本身。

    1
    2
    3
    4
    fun LibraryThing.Companion.myExtension() ="foo"

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

    因此,您可能会发现一些Kotlin库仅在这种情况下添加了空的伴随对象。其他人则不然,对于那些人,您"倒霉"。由于Java没有伴随对象,因此您也不能对Java执行相同的操作。

    另一个通常要求的功能是采用现有的Java静态方法,该方法将类的实例作为第一个参数,并使其充当扩展函数。问题KT-5261,KT-2844,KT-732,KT-3487和其他可能的功能要求对此进行了跟踪。


    您可以为object定义扩展功能,并在系统范围内使用它。一个对象将仅创建一次。

    1
    2
    3
    4
    5
    6
    7
    object MyClz

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

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

    要么

    1
    2
    3
    4
    5
    6
    7
    8
    9
    class MyClz {
        companion object
    }

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

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