holgerbrandl
08/29/2022, 2:35 PMimport kotlin.reflect.KClass
open class Provider {
open fun computeSmthg() = 42
}
class ConfigBuilder(val other: Int = 32) {
fun asProvider(): KClass<*> {
class CustomProvider : Provider() {
override fun computeSmthg(): Int {
return other
}
}
return CustomProvider::class
}
}
fun main() {
val providerClass = ConfigBuilder().asProvider()
require(providerClass.constructors.first().parameters.isEmpty())
val constructor = providerClass.constructors.first()
println(constructor.parameters)
println(constructor)
println(constructor.call())
}
which fails with
fun <init>(): com.systema.nexperia.epi.solver.`ConfigBuilder$asProvider$CustomProvider`
Exception in thread "main" java.lang.IllegalArgumentException: Callable expects 1 arguments, but 0 were provided.
Could I rewrite the code from above to actually create CustomProvider with a zero-arg constructor while referring to òther
property?holgerbrandl
08/29/2022, 7:38 PMkotlin-scripting-jsr223
we can simply compile the class in place with the value using
class ConfigBuilder(val other: Int = 32) {
fun asProvider(): KClass<*> {
return with(ScriptEngineManager().getEngineByExtension("kts")) {
eval(
"""
import com.systema.nexperia.epi.solver.Provider
class CustomProvider : Provider() {
override fun computeSmthg(): Int {
return ${other}
}
}
CustomProvider::class
"""
) as KClass<Provider>
}
}
}
By doing so we can build the type with the value from outer scope, while maintaining an zero argument constructorTóth István Zoltán
08/31/2022, 4:13 AMCustomProvider
class?Tóth István Zoltán
08/31/2022, 4:18 AMfun asProvider() : () -> Provider {
...
return { CustomProvider() }
}
...
ConfigBuilder().asProvider().doSomething()
Still feels quite wrong, but is probably better that the scripting call (which brings up the whole compiler toolchain during runtime, introduces a lot of security problems... brrrr...).Tóth István Zoltán
08/31/2022, 4:20 AMConfigBuilder
implement that interface. No need for CustomProvider
.