Kotlin方差问题

时间:2018-07-11 21:22:36

标签: kotlin covariance contravariance

我正在研究节点链的概念,每个节点可能具有不同的输入和输出类型(尽管输入/输出类型都将源自共享的父类型),其中数据是从节点传递的到节点并一路转换。这是一个示例:

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>,并且不允许CircleNodeNode<Oval, Circle>)。我对方差的理解不足以弄清实现此目标所需的条件(或者是否有可能?)。这可能吗?我在正确的轨道上吗?

1 个答案:

答案 0 :(得分:0)

您使用的类型Node<in Shape, out Shape>Node<Shape, *>等效。因此,您只能添加InputTypeShape的类型。对于您的用例,应使用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)
    }
}