I have the following simple class hierarchy.
abstract class B {
abstract val o : Int
}
class D1 (m: Int, n: Int) : B() {
override val o = m n
}
class D2 (m: Int, n: Int) : B() {
override val o = m * n
}
I need a "factory function" f
that gives me instances of D1
or D2
by calling it as f<D1>()
or f<D2>()
with hard coded parameters, say 3
and 4
. The following doesn't work but illustrates what I need:
// won't compile; just demonstrates what I need
fun < T : B > f () : T {
return T(3, 4) // i. e. return T.constructor(m, n)
}
How to best accomplish this? Any DRY way is fine as long I don't have to repeat 3, 4
all over my code when I instantiate D1
or D2
CodePudding user response:
The only way to do it is via reflection and reified type parameter:
inline fun <reified T : B> f(m: Int = 3, n: Int = 4): T {
val constructor = T::class.constructors.first {
it.parameters.size == 2 &&
it.parameters.all { param -> param.type == Int::class }
}
return constructor.call(m, n)
}
CodePudding user response:
Here's an alternate way without reflection, but you have to manually type out a line for each class you want to handle.
inline fun <reified T : B> f(): T{
val m = 3
val n = 4
return when (T::class) {
D1::class -> D1(m, n)
D2::class -> D2(m, n)
else -> error("Unsupported type ${T::class}")
} as T
}