2017-09-03 61 views
3

考慮下面的兩個代碼。他們完成相同的目標:只有這樣A[T] -s可以存儲在T延伸C斯卡拉存在與協方差

但是他們使用兩種不同的方法來實現這一目標的Container

1)existentials

2)協方差

我更喜歡第一種解決方案,因爲A保持簡單。爲什麼我會想要使用第二種解決方案(協方差),有什麼理由嗎?

我與第二個解決方案的問題是,它是在這個意義上,它不應該是A -s責任來形容我可以在一個容器倉庫並沒有什麼不自然,這應該是容器的責任。第二種解決方案也是更復雜一旦我想開始在A上運行,然後我必須處理所有與協變有關的東西。

使用第二種(更復雜,不太自然)的解決方案會帶來什麼好處?

object Existentials extends App { 

    class A[T](var t:T) 

    class C 

    class C1 extends C 

    class C2 extends C 

    class Z 

    class Container[T]{ 
    var t:T = _ 
    } 

    val c=new Container[A[_<:C]]() 
    c.t=new A(new C) 
    // c.t=new Z // not compile 

    val r: A[_ <: C] = c.t 

    println(r) 
} 

object Cov extends App{ 
    class A[+T](val t:T) 

    class C 

    class C1 extends C 

    class C2 extends C 

    class Z 

    class Container[T]{ 
    var t:T = _ 
    } 

    val c: Container[A[C]] =new Container[A[C]]() 
    c.t=new A(new C) 
    //c.t=new A(new Z) // not compile 

    val r: A[C] = c.t 

    println(r) 
} 

EDIT(響應阿列克謝的答案):

評論: 「我與第二個解決方案的問題是,它不是在某種意義上說,它不應該是作爲責任自然描述我可以在集裝箱中儲存什麼,哪些不是,這應該是集裝箱的責任。「

如果非要class A[T](var t:T)這意味着,我可以僅存儲A[T]在容器-s和不(A[S]其中S<:T),在任何容器。

但是,如果我有class A[+T](var t:T)那麼我可以存儲A[S]哪裏S<:T以及任何容器。

因此,當聲明A或者是不變的或協變時,我決定哪種類型的A [S]可以存儲在一個容器中(如上所示),這個決定發生在聲明A

不過,我認爲,這個決定應該發生,相反,在容器的聲明,因爲它是具體的東西將被允許進入該容器中,只有A[T] -s或也A[S]其中S<:T -s容器。

換句話說,改變A[T]方差具有全球影響,同時改變一個容器的類型參數從A[T]A[_<:S]已經容器本身上的良好限定的局部作用。所以「變化應該有局部效應」的原則也有利於生存解決方案。

回答

4

在第一種情況下,A更簡單,但在第二種情況下它的客戶是。由於通常有多個地方使用A,這通常是值得的折衷。你自己的代碼演示了它:當你需要在第一種情況下(在兩個地方)寫A[_ <: C]時,你可以在第二種情況下使用A[C]

此外,在第一種情況下,你可以只是A[C]其中A[_ <: C]是真正需要的。比方說,你有一個方法

def foo(x: A[C]): C = x.t 

現在你不能叫foo(y)y: A[C1]即使它將使意義:y.t確實有型C

當這種情況發生在您的代碼中時,它可以被修復,但第三方呢?

當然,這適用於標準庫的類型以及:如果類型,如MaybeList不協變,無論是對所有簽名方法服用/返回他們將不得不更加複雜或許多程序這是目前有效並做出完美的感覺會打破。

它不應該是我的責任來描述我可以在一個容器中存儲什麼,什麼不是,這應該是容器的責任。

差異不是關於什麼,你可以存儲在一個容器;它是關於何時A[B]A[C]的子類型。這個說法有點像說你不應該有extends:否則class Apple extends Fruit允許你存儲AppleContainer[Fruit],並決定是Container的責任。

+0

感謝您的回答。 「另外,如果你忘記在一種方法中使用正確的存在,任何其他調用它的地方都不能使用存在類型(沒有不安全的未經檢查的轉換)。」你能舉一個簡單的例子嗎?我不完全明白你的意思。 – jhegedus

+0

「在第一種情況下,A更簡單,但在第二種情況下,其客戶是這樣。」客戶如何更簡單?我不明白,你能舉個例子嗎? – jhegedus

+0

@jhegedus查看編輯。 –