2017-06-24 79 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不能逆變(或協變,對於這個問題)。

相關問題