2017-06-24 76 views
1

我正在尝试在scala中构建行为树库,但我遇到了方差问题。下面是一个节点的简化版本:使用逆变类型参数为方法的类型参数和返回类型时的难度

sealed trait State[+O] 
case class Running[+O](curOut: O, node: Node[O,_]) extends State[O] 
case class Success[+O](out: O) extends State[O] 
case object Failure extends State[Nothing] 

trait Node[-I,C] { 
    protected def canRun(item: I, context: C, tick: Int): Boolean 
    protected def run[O <: I](item: I, context: C, tick: Int): State[O] 

    def apply[O <: I](item: I, context: C, tick: Int): State[O] = { 
     if (canRun(item, context, tick)) run(item, context, tick) 
     else Failure 
    } 
} 

每当我试图然而实例Node,它抱怨说method run overrides nothing

val node = new Node[Int,Any] { 

    override protected def run(item: Int, context: Any, tick: Int): State[Int] = ??? 

    override protected def canRun(item: Int, context: Any, tick: Int): Boolean = ??? 
} 

我试图改变ONode一种类型的成员,但该抱怨Covariant I is used in contravariant position

type O <: I 

我想问的是如何我可以使用反变量类型参数作为方法参数和方法返回类型的类型吗?理想情况下,我不希望在父节点和装饰节点中使用I逆变换的可重用性。

在此先感谢

回答

2

要回答你的问题

我怎么可以用一个逆变类型参数作为一个方法参数和方法返回类型的类型?

不能在方法参数和返回类型中都使用conta-(或co) - 变量类型参数。

我的解决此问题的建议是从Running案例类中删除node参数。或者用只读特征替换参数。例如:

case class Running[+O](curOut: O, process: Process[O]) extends State[O] 
trait Process[+O] { 
    def currentState: State[O] 
} 
2

它抱怨说,运行的方法覆盖任何

这是因为重载方法必须具有相同类型的参数,你只需更换IC,所以在这种情况下,它必须是

new Node[Int,Any] { 

    override protected def run[O <: Int](item: Int, context: Any, tick: Int): State[O] = ??? 

    override protected def canRun(item: Int, context: Any, tick: Int): Boolean = ??? 
} 

请注意,你这个签名说“来电者可以得到State[O]的任何O <: Int它想要“,例如Nothing。你不能真正用这个签名来实现一个方法。

如果你想获得这个签名为run,然后在Node它可能应该是

protected def run(item: I, context: C, tick: Int): State[I] 

这意味着I不能逆变(或协变,对于这个问题)。

相关问题