我有一个类,它需要一个工厂,当提供了一个子类的样本值时,它将创建一个带有子类的类的新对象。例如
open class Base(val i:Int){
fun <T:Base>factory(sample:T, n:Int) = Base(i) // need sample." invoke constructor" (i) as T
}当使用Base的任何子类作为参数调用时,你有什么想法让它工作,而不需要添加样板,或者超越KotlinJS可用的反射来覆盖未来每个子类的工厂吗?
发布于 2020-10-20 21:57:25
open class Base(val i: Int) {
fun <T : Base> factory(sample: T, @Suppress("UNUSED_PARAMETER") n: Int): Base {
@Suppress("UNUSED_VARIABLE") val constructor = sample::class.js
return js("new constructor(n)") as Base
}
override fun toString() = "Base($i)"
}
class Derived(i: Int) : Base(i) {
override fun toString() = "Derived($i)"
}
fun main() {
println(Base(10).factory(Derived(20), n = 5)) // "Derived(5)"
}发布于 2020-10-19 20:04:17
首先,你最好使用具体化的类型参数,这样你的工厂就不需要sample参数了。其次,如果您的工厂将返回泛型类型的对象,那么您将不需要在子类中覆盖它-它将返回所需类型的实例。
但是我不知道没有reflection该怎么做
open class Base (val i: Int) {
inline fun <reified T : Base> factory(n: Int): T {
val kClass = T::class
val constructor = kClass.constructors.find { it.parameters.size == 1 && it.parameters[0].type == Int::class }
?: throw RuntimeException("Constructor with single Int parameter was not found for ${kClass.qualifiedName} class")
return constructor.call(n)
}
}用法:
open class Derived(i: Int) : Base(i)
open class Derived2(i: Int) : Derived(i)
//any subclass of Base or Base itself when called on instance of Base
val base = Base(1)
val a: Base = base.factory(1) //or val a = base.factory<Base>(1)
val b: Derived = base.factory(1)
val c: Derived2 = base.factory(1)
//any subclass of Base or Base itself when called on any instance of Base subclass
val derived2 = Derived2(1)
val a1: Base = derived2.factory(1)
val b1: Derived = derived2.factory(1)
val c1: Derived2 = derived2.factory(1)https://stackoverflow.com/questions/64419920
复制相似问题