2016-07-05 69 views
2

我是scala中的新成員。我想弄清楚整個逆變關係是如何工作的。我理解協變和不變的概念,我也知道如何在實踐中實現它們。 我也理解逆變的概念(協方差的倒數)以及它如何在Scala的Function1特性中實現。它爲您提供了一個抽象,而不用爲不同的類重新定義Function1實現。但是,我仍然不完全明白,奇怪?現在,我幾乎沒有...我怎樣才能解決以下問題逆變:scala中的逆變法

class GarbageCan[-A] { 

    def doSomething(a: A): Unit ={ 
    // do something with 'a' of subtype that is not possible with the supertype 
    } 

} 

def setGarbageCanForPlastic(gc: GarbageCan[PlasticItem]): Unit = { 

} 

上面的例子是從http://blog.kamkor.me/Covariance-And-Contravariance-In-Scala/提取。關於這個問題的一個非常好的解釋。層次結構如下:Item(基類) - > PlasticItem(子類) - > PlasticBottle(子類的子類)

setGarbageCanForPlastic函數接受類型爲PlasticItem的GarbageCan。因爲參數類型是逆變的,下面的語句是完全合法的:

setGarbageCanForPlastic(new GarbageCan[Item]) 

現在,DoSomething的函數接受一個類型參數是逆變的。如果我不知道類型是基類「Item」還是子類「PlasticItem」,我該如何處理這種類型?我可以做一些在子類中允許的,而不是在基類中允許的。如果這是一個協變參數,這將是沒有問題的,一個子類繼承了基類中的所有內容。

我失去了它的權利?...希望有人能幫助我。

+0

你爲什麼只擔心'GarbageCan [Item]'?例如,有什麼來防止有人創建'GrabageCan [Option [List [Int]]]'?暫時忽略逆變方差。即使它只是'GrabageCan [A]',你怎麼想象你的'doSomething'會起作用? – Dima

+0

好問題......它只能用作身體內的「類型」? –

+1

嗯,我不確定你的意思是什麼,它是什麼意思,所以我不知道:)底線是,你首先想出一個實際的用例,然後_then_看看反變量/協方差/不變性是否適合它,而不是相反。 – Dima

回答

1

首先,doSomething方法除了基本上丟棄a之外實際上不能做任何事情,因爲它不知道A是什麼。爲了使它更有用,你需要一個像class GarbageCan[-A <: Item]這樣的界限。

現在,假設setGarbageCanForPlastic(gc)調用gc.doSomething(new PlasticItem)。由於GarbageCan[A]中的A是逆變,因此我們有GarbageCan[Item] <: GarbageCan[PlasticItem] <: GarbageCan[PlasticBottle]。事實上,函數調用setGarbageCanForPlastic(new GarbageCan[Item]))是安全的,因爲GarbageCan[Item]doSomething可以處理任何Item包括PlasticItem,在呼叫setGarbageCanForPlastic(new GarbageCan[PlasticBottle]))是不安全的,因爲GarbageCan[PlasticBottle]doSomething可能無法採取PlasticItem這不一定是PlasticBottle

+0

太棒了!感謝您的闡述。 –