我有以下类/接口:
interface A
interface Factory<in SpecType: Factory.Spec> {
interface Spec
fun create(spec: SpecType): A
}
class DefaultFactory : Factory<DefaultFactory.Spec> {
data class Spec(
val message: String
) : Factory.Spec
override fun create(spec: Spec): A {
// Do stuff here to create an instance of A using spec
}
}
然后在另一个班级,我想提供一个可以替换的默认工厂。
var factory: Factory<???> = DefaultFactory()
无论我似乎尝试替换???
,我都无法让它运作良好。如果使用接受Spec
的工厂然后传递给另一个工厂,我不介意在运行时崩溃。我发现的唯一有用的是:
@Suppress("UNCHECKED_CAST")
var factory: Factory<Factory.Spec> = DefaultFactory() as Factory<Factory.Spec>
但这看起来很丑陋而且似乎错了。
答案 0 :(得分:0)
明显的答案是var factory:Factory<DefaultFactory.Spec> = DefaultFactory()
但我认为你需要更复杂的东西。
实际上你可能需要这样的提供者界面:
interface Factory<in SpecType: Factory.Spec> {
interface Spec
fun create(spec: SpecType): A
val spec: SpecType
}
然后你的实现看起来像
class DefaultFactory : Factory<DefaultFactory.Spec> {
override val spec: Spec
get() = Spec("test message")
override fun create(spec: Spec): A {
TODO("not implemented")
}
data class Spec(val message: String) : Factory.Spec
}
它对我来说看起来非常有效,但如果没有关于您的业务的详细信息,就无法解决您的难题。为什么你认为你需要通用?
答案 1 :(得分:0)
实际上有一种类型可以安全地用于???
:var factory: Factory<*>
。唯一的小问题是,您无法将任何内容传递给create
(或者更确切地说,您只能传递Nothing
)。
这是因为安全代码不允许
如果使用接受Spec的工厂然后传递另一个工厂,则在运行时崩溃。
如果你想要它,你需要在某个地方进行不安全的施放或在某个地方投掷,而应该&#34;看起来很丑陋而且看起来是错误的&#34;。
这有点好,因为它提供了一个有用的例外:
inline fun <reified T : Factory.Spec> Factory<T>.upcast(): Factory<Factory.Spec> =
object : Factory<Factory.Spec> {
override fun create(spec: Factory.Spec): A =
if (spec is T)
this.create(spec)
else throw IllegalArgumentException("Bad spec type, need ${T::class}")
}
var factory: Factory<Factory.Spec> = DefaultFactory().upcast()
如果create
返回A?
,则可以使其安全;只是因为这个原因,不要让它返回A?
!