修补否则协类的典型例子如下:逆变哪里?
abstract class Stack[+A] { def push[B >: A](x: B) : Stack[B] def top: A def pop: Stack[A]
现在,如果我去掉隐含协方差和手动标注类,我得到这个:
abstract class Stack[A] { def push[B >: A](x: B) : Stack[B] def top [B >: A]: B def pop [B >: A]: Stack[B] def cast[B >: A]: Stack[B] }
(快速正确性证明:a Stack[A]
具有A
类型的元素,因此如果B
更宽容,我们总是可以返回A
而不是B
。同样,如果有任何堆栈A
,我们可以使用它代替堆栈如果B可以接受A.)
但是现在我有点困惑:在这里应该有一个逆变,但是这里的所有子类型关系似乎都是一样的。发生了什么?
为了详细说明,我们定义了一个逆变函数F
,例如(a -> b) -> (F b -> F a)
。特别地,a -> r
上的函数F a
是逆变的,因为(a -> b) -> ((b -> r) -> (a -> r))
只是通过组合函数。从形式主义的角度来看,我预计箭头会翻转。所以从纯粹的语法角度来看,当没有箭头翻转时(但应该是!),我会感到困惑吗?我写注释的Scala写作方式只是函数反转的“自然”表示,因此您甚至不会注意它?我的抽象类错了吗?第二个演示文稿有误导吗?
而问题是......什么? “这里应该有什么反差”是什么意思? – 2011-05-24 16:17:42
当我被告知一个关系是逆变的时,我期望存在一个子类型关系'A <:B'和一个相应的子类型关系'F A>:F B':我期望箭头翻转。但我在这里的任何地方都看不到。那么我写下的代码的特定部分是否使得'push'逆变的论点? – 2011-05-24 16:20:29
在scala中,方差注释“ - ”表示类型是逆变的。你的堆栈类型没有这种关系,并且在任何情况下,即使你添加了一个'Stack [Apple]',也不是超级类型的'Stack [Fruit]'。 – 2011-05-24 16:36:51