为什么在覆盖方法专门化的参数类型一般化?

时间:2018-01-28 23:52:51

标签: oop covariance contravariance

我正在阅读的这本书刚刚介绍了包含,协方差,逆变及其对编程语言设计的影响的概念。现在,在关于方法专业化的部分中,我遇到了麻烦。

本书指出,当我们覆盖子类中的方法时,可以推广参数类型,并且可以使用结果类型。但是,本书认为,对于未被重写但继承的方法,另一种类型的方法专业化正在发挥作用,其中参数类型是专用的,结果类型是通用的,因为我们可以将self关键字解释为参数:

“还有另一种形式的方法专业化,它是通过继承隐式发生的。在C的方法中,self的出现可以被认为是C类,因为绑定到self的所有对象都有C类或C的子类型当C的方法由C'继承时,同样出现的self同样可以被认为是C'类型。因此,self的类型默默地专注于继承(covariantly!)。“

这是我的问题:我们不能将self关键字视为重写方法中的协变参数吗?然后我们最终将this关键字作为协变参数,尽管我们刚刚确定,由于替换原则,重写方法的参数需要是逆变的。我忽略了什么吗?

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

编程语言中方差的实现

  

...当我们覆盖子类中的方法时,参数类型可以是通用的(协方差),结果类型可以是专门的(逆向

即使这可能是真的,但它取决于特定的语言,是否实际实现了此功能。我找到了examples on wiki

  • C ++和Java只实现协变返回类型和方法 参数类型是不变的。

  • C#没有实现任何变量(所以两者都是不变的)。

  • 有一个带有逆变参数类型和协变返回类型的语言(Sather)的例子 - 这就是你提到的。
  • 然而,还有一个(艾菲尔)协变返回& 参数类型,但此 通常会导致运行时错误。

控制和“遗留”参数

There也是一个很好的段落,用于区分控制参数和“ left-over ”参数之间的参数。控制的是协变的,非控制的是逆变的。这是关于多个调度语言,虽然大多数情况下你指的是一种调度语言。但即使只有一个控制论点(self / this)。

以下是段落(我没有时间研究paper it is referring to,如果您有时间并发布您的调查结果,请随时阅读):

  

Giuseppe Castagna [3]观察到,在具有多个调度的类型语言中,泛型函数可以有一些控制调度的参数和一些“ left-over “没有的论据。由于方法选择规则选择最具体的适用方法,如果方法覆盖另一个方法,则覆盖方法将具有更多特定类型的控制参数 。另一方面,为了确保类型安全,语言仍然必须要求 left-over 参数至少是一般的。使用前面的术语,用于运行时方法选择的类型是协变,而不用于方法的运行时方法选择的类型是逆变的

     

像Java这样的传统单调度语言也遵循这个规则:只有一个参数用于方法选择(接收者对象,作为隐藏参数传递给方法this),实际上是this在重写方法中比在超类中更专业。

问题

根据该段我假设 self论证的性质不是常规方法论证(可能是逆变),因为self是另一种论点 - 控制论证 - 是协变的

  

......即使我们刚刚确定,由于替代原则,被覆盖方法的论据需要是逆变的。

嗯,它看起来不是全部。