我是否必须在子类型中指定类型差异?
问题描述:
比方说,我有一个特质我是否必须在子类型中指定类型差异?
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))
}
感谢
答
好吧,让我们做一个小测试。
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]
所以是的,它确实有所作为。如果你想把你的子类型暴露给世界,不要把它作为一个私有的内部实现,最好添加适当的方差注释。
我不认为你需要添加变体以及子类型。变体指定了子类型和超类型之间的关联。 – Sakalya
我也这么想。但是这两种语法都显然是有效的,所以我很困惑。 – Midiparse
这两种语法都是有效的。但是使子类型为[-Int],将使其子类不变。 – Sakalya