我正在研究节点链的概念,每个节点可能具有不同的输入和输出类型(尽管输入/输出类型都将源自共享的父类型),其中数据是从节点传递的到节点并一路转换。这是一个示例:
open class Shape
open class Oval : Shape()
class Circle : Oval()
class NodeChain {
val nodes: MutableList<Node<in Shape, out Shape>> = mutableListOf()
fun node(n: Node<in Shape, out Shape>) {
val prevNode = nodes.lastOrNull()
nodes.add(n)
prevNode?.nextNode = n::processInput
}
fun processInput(input: List<Shape>) {
nodes[0].processInput(input)
}
}
abstract class Node<InputType : Shape, OutputType : Shape> {
var nextNode: Function1<List<OutputType>, Unit>? = null
abstract fun processInput(input: List<InputType>)
}
class OvalNode : Node<Shape, Oval>() {
override fun processInput(input: List<Shape>) {
nextNode?.invoke(listOf(Oval()))
}
}
class CircleNode : Node<Oval, Circle>() {
override fun processInput(input: List<Oval>) {
nextNode?.invoke(listOf(Circle()))
}
}
val nodeChain = with (NodeChain()) {
node(OvalNode())
node(CircleNode()) // Error[1] here (listed below)
this
}
Erorr[1]:
Type mismatch.
Required:
Scratch_3.Node<in Scratch_3.Shape, out Scratch_3.Shape>
Found:
Scratch_3.CircleNode
最后您会看到一个错误:尝试向链中添加“ CircleNode”时,它抱怨期望Node<in Shape, out Shape>
,并且不允许CircleNode
( Node<Oval, Circle>
)。我对方差的理解不足以弄清实现此目标所需的条件(或者是否有可能?)。这可能吗?我在正确的轨道上吗?
答案 0 :(得分:0)
您使用的类型Node<in Shape, out Shape>
与Node<Shape, *>
等效。因此,您只能添加InputType
为Shape
的类型。对于您的用例,应使用Node<*, *>
添加Node
的任何扩展名:
class NodeChain {
val nodes: MutableList<Node<*, *>> = mutableListOf()
fun node(n: Node<*, *>) {
val prevNode = nodes.lastOrNull()
nodes.add(n)
prevNode?.nextNode = n::processInput
}
fun processInput(input: List<Shape>) {
nodes[0].processInput(input)
}
}