我是否必须在子类型中指定类型差异?

问题描述:

比方说,我有一个特质我是否必须在子类型中指定类型差异?

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

好吧,让我们做一个小测试。

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] 

所以是的,它确实有所作为。如果你想把你的子类型暴露给世界,不要把它作为一个私有的内部实现,最好添加适当的方差注释。