Kotlin 泛型:为什么超类型是"SomeActor : DataActor<SomeData>" "DataActor<out SomeData>"而不是"DataActo



我已经构建了一个最小的例子来显示我的问题。我已经知道一个丑陋的解决方案,但我想找到一个更好的解决方案。

兴趣线:29:val actor: DataActor<out Data> = when ...添加"out"使得不可能调用以Data作为参数的函数(例如第36行)。

有了这个问题,我就能明白问题是什么了:如果类型为DataActor<Data>,则可以向任何Actor添加任何数据。例如:可以将Text加入NumberActor。因为我只使用SomeActor产生的数据作为SomeActor的可消费,所以我知道它可以保存。

但是这个问题没有回答的是:什么是隐含的习惯用法?我想要的功能?

我能想到的唯一解决方案是在when子句中执行所有操作,但在实际应用程序中,这将导致大量代码重复。

interface Data
class Text(var text: String) : Data
class Number(var number: Int) : Data
interface DataActor<A: Data> {
fun add(element: A): Boolean;
fun get(index: Int): A
}
class TextActor : DataActor<Text> {
private val list = ArrayList<Text>()
override fun add(element: Text) = list.add(element)
override fun get(index: Int): Text = list[index]
}
class NumberActor : DataActor<Number> {
private val list = ArrayList<Number>()
override fun add(element: Number) = list.add(element)
override fun get(index: Int): Number = list[index]
}
enum class Selector {
Number,
Text
}
fun main() {
val selector = Selector.Number
// Why is it from type DataActor<out Data> and not DataActor<Data>?
val actor = when(selector) {
Selector.Number -> NumberActor()
Selector.Text -> TextActor()
} // as DataActor<Data> // ugly solution
val data = actor.get(0)
// This is not possible as it needs DataActor<in Data> or DataActor<Data>
actor.add(data)
}

我想你已经解释过你已经理解这个问题了。这两个类没有相同的不变超类型。它们只能有一个共同的协变超类型。

所以要解决这个问题,需要将维护不变性的代码拆分为它自己的泛型函数。在泛型函数中,T是不变的。它不关心它是哪个T,所以代码是安全的。

fun main() {
val selector = Selector.Number
val actor = when(selector) {
Selector.Number -> NumberActor()
Selector.Text -> TextActor()
} 
doWork(actor)
}
fun <T: Data> doWork(actor: DataActor<T>) {
val data = actor.get(0)
actor.add(data)
}

这当然是基于你的非常简单的例子。对于更复杂的情况,例如试图在这些类的不同实例之间传输项时,此解决方案可能不可行。

相关内容

  • 没有找到相关文章

最新更新