Can a constructor be written as an extension metho...
# announcements
s
Can a constructor be written as an extension method?
c
You can make a factory function on a class’s companion object, if it exists. The semantics of it are a bit strange and can be pretty unintuitive, but it can be done. For example:
Copy code
operator fun String.Companion.invoke(any: Int) : String {
    return any.toString()
}

fun callStringFactory() {
    val s: String = String(123)
}
s
Ah awesome, I had stumbled onto something like that online
I’m having trouble doing the same to a generic class, though
c
I don’t think you’ll be able to make a generic function out of it, since not all classes have companion objects, and there’s no way to declare an interface or anything on a class to mandate that it has one
s
Right, I was trying to get around it by using interfaces, but it wasn’t accessible, like you mentioned
Maybe I should say what I’m trying to accomplish instead! I’m trying to create a DSL that can take any sealed class as a generic property, then operate on it using it’s invoke function.
Copy code
sealed class Model {
  class A: Model()
  class B: Model()
}

class Dsl<T>()

fun <T> dsl(init: Dsl<T>.() -> Unit): Dsl<T> {
  // DSL boilerplate
}

val test = dsl<Model> {
  Model.A {
    // Do stuff
  }
  Model.B {
    // Do stuff
  }
}
c
You might go with an approach like Ktor, where you declare an interface on the companion object itself. And then the DSL function can look for that interface
Copy code
interface DslCompanionInterface

sealed class Model {
    class A: Model() {
        companion object : DslCompanionInterface
    }
    class B: Model() {
        companion object : DslCompanionInterface
    }
}

class Dsl<T>() {
    operator fun T.invoke(block: ()->Unit) {

    }
}

fun <T : DslCompanionInterface> dsl(init: Dsl<T>.() -> Unit): Dsl<T> {
    // DSL boilerplate
}

val test = dsl<DslCompanionInterface> {
    Model.A {
        // Do stuff
    }
    Model.B {
        // Do stuff
    }
}
s
That looks pretty promising! I’ll give that approach a shot and play around with it
It looks like it may be more promising to just require that the parent sealed class be composed of objects, and to figure out another solution for State. Thanks!