how do I call the constructor of a generic type? S...
# getting-started
k
how do I call the constructor of a generic type? Say I have something like
Copy code
class foo<T: Interface>() {
    var something: T? = null
    init {
        something = T("bar") //doesn't work
    }
}
I have an interface, the implementing classes of which have a constructor that takes one string. I'd like to make a class that can take any type that implements the interface and be able to cosntruct an instance of said class.
1
j
You can't, because you cannot guarantee that every
T
that implements
Interface
will have a constructor that takes a single string argument.
What are you trying to do, in a broader sense? This sounds like an XY problem
k
I have a machine translation program that can implement several translation APIs like google translate and deepl. These are implemented as children of a common interface. I'd like to also add tornadoFX fragments that can set the api key of each of these classes through a settings dialog. Right now I have a separate form for each but this duplicates code when really the only unique part of the settings form is the type of translation backend class it uses
if I made the interface an abstract class instead and gave it a constructor with the same arguments this would work then?
v
Same problem. Just that the abstract class has that constructor does not mean a subclass has such a constructor.
k
so the generics can't really be used with polymorphism then?
what's the idiomatic workaround to not being able to construct the generic type?
s
Copy code
class Foo<T>(val something: T) {
    constructor(init: (String) -> T): this(init("bar"))
}

class Bar(val value: String)

val foo = Foo(::Bar)
2
j
You can pass a function to the
Foo
class
Ah, Sam beat me to it 😄
k
yeah just found on stack overflow to pass a (String) -> T to it
ty
j
You can also store the function itself as a property of the class, if you need to use it multiple times, or call it later instead of immediately at construction time:
Copy code
class Foo<T>(private val createThing: (String) -> T) {
    fun doStuff() {
        val thing = createThing()
        // ...
    }
}