我在玩scala的类型系统,发现了一个奇怪的情况。我有充分的理由相信,我不理解协变和协方差。
这是我的问题:
我有两个类,Point和ColorPoint,它是Point的子类。
class Point(val x : Int, val y : Int)
class ColorPoint(x : Int, y : Int, val red : Int, val green : Int, val blue : Int) extends Point(x,y) 这个类将B转换为A,而B应该是A的超级类型:
class CoVariance[+A]{
def cast[B >: A](x : B) : A = {
return x.asInstanceOf[A]
}
}这个类将B转换为A,而B应该是A的超级类型:
class ContraVariance[-A]{
def cast[B, A <: B](x : B) : A = {
return x.asInstanceOf[A]
}
}案例1:
val co = new CoVariance[Point]
val color_point = new ColorPoint(1,2,3,4,5)
val point_co = co.cast(color_point)
println(point_co.x)如果我把这个写出来
// Covariance[Point] ->
// cast[B :> Point](x : B) : Point -> (fill in ColorPoint)
// Cast[ColorPoint :> Point] : Point 我认为这是不正确的,因为ColorPoint不是Point的超级类型,但是scala没有抱怨。
下一个:
val contra = new ContraVariance[Point]
val color_point_contra = new ColorPoint(1,2,3,4,5)
val point_contra = contra.cast(color_point_contra)
println(point_contra.x)如果我把这个写出来
// ContraVariance[Point] ->
// cast[B, Point <: B](x : B) : Point -> (fill in ColorPoint)
// cast[ColorPoint, Point <: ColorPoint] : Point 我也希望这是不正确的,但scala没有抱怨。我想说,Point不是ColorPoint的一个子类型。
我的推理是正确的还是我遗漏了什么?
发布于 2013-10-29 20:36:37
我想你误解了什么是共变和对立的位置。这并不意味着您可以在某些类型之间进行转换,它只是建立了参数化类型之间的继承关系。
您只能标记类型参数,如在协变或对变量位置。当您说Container[+A]时,您的意思是,如果Container[A]是B的子类型,则可以将A的所有实例视为Container[B]的子类型。对于不可变的容器类来说,这是有意义的:您可以认为List[Person]是List[Employee]的父类。请注意,这并没有说明转换规则--这些规则没有改变。
反变体是相似的,但恰恰相反。如果有Writer[-A],则表示Writer[A]是Writer[B]的子类型,如果B是A的子类型。您也可以看到这是如何直观地理解的:如果您有一个Writer[Person],它可以将一个人写进某个目的地,而Writer[Employee]是一个只能写员工的作者,那么Writer[Employee]作为Writer[Person]的父母是有意义的,因为编写Person是编写完整的Employee的一个子任务,尽管类型本身正好相反。
发布于 2013-10-29 20:38:05
asInstanceOf[T]忽略了打字机。所以你甚至可以有以下演员阵容:
def castB:B = a.asInstanceOfB
用于任何A和B。
因此,就您的情况而言,Scala不会抱怨。cast方法。我认为,您不必在类声明中使用+/-。只有两种不同的类型:
隐式类CastToParentA { def castB >:A:B = a.asInstanceOfB }隐式类CastToChildA { def castB <:A:B = a.asInstanceOfB }
这允许您进行所需的转换。
特征A特征B扩展A性状C val a:A =新B {} val = a.castB //parent to child val a1 = b.castA //child to parent。val = a.castC //不编译https://stackoverflow.com/questions/19668353
复制相似问题