我正在阅读的书刚刚介绍了包含,协方差,逆变的概念及其对编程语言设计的影响。现在,在关于方法专业化的部分中,我遇到了麻烦。
书中指出,当我们覆盖子类中的方法时,参数类型可能是泛化的,结果类型可能是专门的。然而,这本书认为,对于没有被覆盖而是继承的方法,另一种类型的方法专用化正在发挥作用,其中参数类型是专用的,结果类型是通用的,因为我们可以将 self 关键字解释为参数:
"还有另一种形式的方法专业化,它通过继承隐含地发生。在 C 的方法中,self 的出现可以被认为是 C 类型,从某种意义上说,绑定到 self 的所有对象都具有类型 C 或 C 的子类型。当 C 的方法被 C' 继承时,同样可以认为 C' 型的自我出现相同。因此,自我的类型默默地专门研究遗传(协变!
这是我的问题:我们不能将 self 关键字也视为重写方法中的协变参数吗?然后我们最终会以 this 关键字作为协变参数,即使我们刚刚确定,由于替换原则,被覆盖方法的参数必须是逆变的。我忽略了什么吗?
感谢您的帮助!
编程语言中方差的实现
。当我们覆盖子类中的方法时,参数类型可能是广义的(协方差),结果类型可能是专门的(逆方差)
尽管这可能是真的,但它取决于特定的语言,它是否实际实现了此功能。我在维基上找到了例子:
-
C++和Java只实现协变返回类型和方法 参数类型是不变的。
-
C# 不实现任一变体(因此两者都是不变的)。
-
有一个具有逆变参数类型和协变返回类型的语言(Sather)的示例 - 这就是您提到的。
-
但是,也有一个(Eiffel)具有协变返回和参数类型,但这通常会导致运行时错误。
控制和"剩余"参数
还有一个很好的段落将控制参数和">剩余">参数分开。控制型是协变的,非控制型是逆变的。这是关于多个调度语言的,尽管您肯定指的是一种调度语言。但即使只有一个控制参数(self
/this
)。
这是一段(我没有时间研究它所指的论文,如果您有时间并发布您的发现,请随时阅读):
Giuseppe Castagna[3]观察到,在具有多个调度的类型语言中,泛型函数可以有一些控制调度的参数和一些不控制调度的">剩余"参数。由于方法选择规则选择最具体的适用方法,因此如果一个方法重写另一个方法,则重写方法将具有更具体的控制参数类型。另一方面,为了确保类型安全,语言仍然必须要求剩余参数至少是通用的。使用前面的术语,用于运行时方法选择的类型是协变的,而不用于方法的运行时方法选择的类型是逆变的。
像Java这样的传统单调度语言也遵循这个规则:只有一个参数用于方法选择(接收器对象,作为隐藏参数传递给方法
this
),事实上,this
的类型在覆盖方法中比在超类中更专业。
问题所在
根据该段,我假设self
参数本质上不是常规方法参数(可能是逆变的),因为self
是另一种参数 -控制参数- 它们是协变的。
。尽管我们刚刚确定,作为替代原则的结果,被覆盖方法的论点必须是逆变的。
好吧,看起来不是全部。