是否可以在Kotlin中创建扩展构造函数?

Ara*_*cem 19 kotlin

在像Swift这样的其他语言中,有可能创建一个添加新构造函数的函数扩展.

像这样的东西:

// base class
class Whatever() {
    ...
}

// constructor method extension
fun Whatever.constructor(potato: String) {
    setPotato(potato)
}

fun main(args: Array<String>) {
    println(Whatever("holi"))
}
Run Code Online (Sandbox Code Playgroud)

在Kotlin有没有办法做到这一点?

Ara*_*cem 24

似乎没有官方的"构造函数的函数扩展",但你可以创建一个模仿构造函数的包方法

class Foo() {
    ...
}

fun Foo(stuff: Int): Foo = Foo().apply {setStuff(stuff)}

fun main(args: Array<String>){
    println(Foo(123))
}
Run Code Online (Sandbox Code Playgroud)

  • 你是对的,但这有区别,你不需要调用Factory.foo(123).无论如何糖代码 (4认同)
  • 虽然这可以模仿用户的构造函数,但这样做也有缺点:/sf/ask/2432632821/ -be避功能于科特林,为什么 (4认同)
  • @WilliMentzel它为客户端模仿一个构造函数:它们以与构造函数相同的方式调用它,并且不需要知道它是什么. (3认同)
  • 这不模仿构造函数,它是工厂模式:) (2认同)
  • @WilliMentzel 对于这个特定用途,我认为它非常好。当然,这只是我的意见。 (2认同)

Wil*_*zel 11

不像Swift,因为:

扩展程序是静态解决的.扩展实际上并不修改它们扩展的类.通过定义扩展,您不会将新成员插入到类中,而只是使用此类型的变量上的点符号使新函数可调用.(来源)


如果在目标类中定义了伴随对象,请使用s1m0nw1的方法.优点是您可以在没有目标类的实例(静态)的情况下调用扩展函数.


如果没有,请使用经典的工厂模式:

class Fruit(var name: String = "") {
}

class FruitFactory {
    companion object {
        fun create(name: String): Fruit {
            return Fruit().apply {
                this.name = "Tasty $name"
            }
         }
    }
}

fun main(args: Array<String>) {
    val orange = Fruit("Orange")
    println(orange.name)

    val apple = FruitFactory.create("Apple")
    println(apple.name)
}
Run Code Online (Sandbox Code Playgroud)

您可以根据需要扩展Factory,使用嵌套或扩展函数作为其他构造函数.

输出:

橙色
美味的苹果


s1m*_*nw1 9

你不能这样做.你可以做什么:companion用工厂方法扩展类的对象:

// base class
class Whatever() {
    companion object {

    }

}

// factory extension
fun Whatever.Companion.withPotato(potato: String) {
    //setPotato(potato)
}

fun main(args: Array<String>) {
    println(Whatever.withPotato("holi"))
}
Run Code Online (Sandbox Code Playgroud)

唯一的问题:companion必须存在一个对象才能执行此操作.


kot*_*oto 5

基于@s1m0nw1解决方案,我可以将其调整为更像覆盖运算符所需的OP invoke

// base class
class Whatever() {
    companion object {
        fun setPotato(potato: String)
    }
}

operator fun Whatever.Companion.invoke(potato: String) {
    setPotato(potato)
}

fun main(args: Array<String>) {
    println(Whatever("holi"))
}
Run Code Online (Sandbox Code Playgroud)

请记住,它仍然需要基类中的伴生对象。如果您无法编辑基类的源代码(如果是 kotlin 框架类或第三方类),并且它已经有您想要添加新方法的伴生对象,那么您始终可以使用扩展函数:

fun Int.Companion.setPotato(potato: String) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)