【发布时间】:2018-12-20 00:26:23
【问题描述】:
我在玩节点链的概念,每个节点都可以有不同的输入和输出类型(尽管输入/输出类型都来自共享的父类型),其中数据从节点传递节点并沿途变换。这是一个例子:
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(即@987654324 @)。我对方差的理解还不足以弄清楚我需要什么来实现这一点(或者它是否可能?)。这可能吗?我在正确的轨道上吗?
【问题讨论】:
-
in Shape只允许Shape的超类型,而不是子类型。Node<Shape, Circle>会工作。Node<Oval, Shape>不会。 -
感谢@LouisWasserman,有没有办法做到这一点?这里有其他的输入/输出组合吗?
-
我怀疑您是否可以拥有您想要的
NodeChain类型。Node中的链接结构及其nextNode字段有效,但您不能让with结构像您希望的那样工作,因为允许下一个节点的类型会随着您添加更多节点而改变。Node单独应该可以工作,直接构建Nodes 链而不需要中间类型应该可以工作。 -
感谢@LouisWasserman,是的,创建和连接节点(没有任何管理链)确实可以正常工作,但希望能够利用“链”来拥有节点并组装它们......我担心,虽然这可能是不可能的:/
标签: kotlin covariance contravariance