我们的代码库具有许多实现的接口。这些被序列化,存储和反序列化。反序列化时,我们调用一个采用接口类型的函数,然后该函数具有一个基于特定类型(即
)分支的巨型when子句。 when (t) {
is SubType1 -> ...
is SubType2 -> ...
is SubType44 -> ...
}
这很麻烦,并增加了功能的复杂性。一种可能性是将我们要执行的动作移至实际的实现本身,因此我们可以仅调用t.doAction()并消除when子句。没关系,但是这种特定的逻辑实际上并不属于实现(出于某种原因),因此最好能够调用参数类型的重载函数,并让kotlin根据实现类型确定要调用的类型。不幸的是,它似乎无法做到。我们得到“以下任何函数都不能使用提供的参数来调用。”
这里是否存在一种可以使编译器满意的模式?
以下为人为的示例。 i1是一个底层的Int,但是编译器无法看到它,因为它被键入为接口,即Number。
fun test() {
val e = Example()
val i1 = 123 as Number
val i2 = 123.0
e.sqrt(i1)
e.sqrt(i2)
}
class Example {
fun sqrt(i: Int) {
}
fun sqrt(i: Double) {
}
}
}
答案 0 :(得分:0)
您可以创建一个Disionion地图。该功能将与新的实现保持不变,只有地图会变得更大:
val map : Map<KClass<*>, (Any) -> Unit> = mapOf(
SubType1::class to { /*SubType1 implementation*/ },
SubType2::class to { /*SubType2 implementation*/ },
...
)
fun <T> execute(item: T) {
map[item::class]?.invoke(item) ?: error("Case not implemented")
}
如果每种情况下都有很多实现行,并且/或者要进行优雅的测试,则可以为每种情况创建一个类,然后分别进行测试:
interface ClassDesicion<T> {
fun execute(item: T) : Unit
}
val map : Map<KClass<*>, ClassDesicion<*>> = mapOf(
SubType1::class to SubType1Implementation(),
SubType2::class to SubType2Implementation(),
...
)