2017-06-12 125 views
4

比方說,我有一個特質我是否必須在子類型中指定類型差異?

sealed trait Expr[-InT, +OutT] { 
    def apply(lhs: InT): OutT 
} 

我想在InT創建一個亞型And逆變。我一定要實現它,因爲這(1):

type BExpr[-InT] = Expr[InT, Boolean] 

final case class And[-InT](exp: BExpr[InT], exps: BExpr[InT]*) extends BExpr[InT] { 
    def apply(lhs: InT) = exps.foldLeft(exp.apply(lhs))(_ & _(lhs)) 
} 

或者是以下就夠了(2)?

type BExpr[InT] = Expr[InT, Boolean] 

final case class And[InT](exp: BExpr[InT], exps: BExpr[InT]*) extends BExpr[InT] { 
    def apply(lhs: InT) = exps.foldLeft(exp.apply(lhs))(_ & _(lhs)) 
} 

感謝

+0

我不認爲你需要添加變體以及子類型。變體指定了子類型和超類型之間的關聯。 – Sakalya

+0

我也這麼想。但是這兩種語法都顯然是有效的,所以我很困惑。 – Midiparse

+0

這兩種語法都是有效的。但是使子類型爲[-Int],將使其子類不變。 – Sakalya

回答

3

好吧,讓我們做一個小測試。

scala> trait A[+T] 
defined trait A 

scala> trait B[T] extends A[T] 
defined trait B 

scala> def b1: B[String] = ??? 
b1: B[String] 

scala> def b2: B[AnyRef] = b1 
<console>:13: error: type mismatch; 
found : B[String] 
required: B[AnyRef] 
Note: String <: AnyRef, but trait B is invariant in type T. 
You may wish to define T as +T instead. (SLS 4.5) 
     def b2: B[AnyRef] = b1 
         ^

scala> def a: A[AnyRef] = b1 
a: A[AnyRef] 

scala> trait B[+T] extends A[T] 
defined trait B 

scala> def b3: B[String] = ??? 
b3: B[String] 

scala> def b4: B[AnyRef] = b3 
b4: B[AnyRef] 

所以是的,它確實有所作爲。如果你想把你的子類型暴露給世界,不要把它作爲一個私有的內部實現,最好添加適當的方差註釋。

相關問題