我正在阅读的这本书刚刚介绍了包含,协方差,逆变及其对编程语言设计的影响的概念。现在,在关于方法专业化的部分中,我遇到了麻烦。
本书指出,当我们覆盖子类中的方法时,可以推广参数类型,并且可以使用结果类型。但是,本书认为,对于未被重写但继承的方法,另一种类型的方法专业化正在发挥作用,其中参数类型是专用的,结果类型是通用的,因为我们可以将self关键字解释为参数:
“还有另一种形式的方法专业化,它是通过继承隐式发生的。在C的方法中,self的出现可以被认为是C类,因为绑定到self的所有对象都有C类或C的子类型当C的方法由C'继承时,同样出现的self同样可以被认为是C'类型。因此,self的类型默默地专注于继承(covariantly!)。“
这是我的问题:我们不能将self关键字视为重写方法中的协变参数吗?然后我们最终将this关键字作为协变参数,尽管我们刚刚确定,由于替换原则,重写方法的参数需要是逆变的。我忽略了什么吗?
感谢您的帮助!
答案 0 :(得分:1)
...当我们覆盖子类中的方法时,参数类型可以是通用的(协方差),结果类型可以是专门的(逆向)
即使这可能是真的,但它取决于特定的语言,是否实际实现了此功能。我找到了examples on wiki:
C ++和Java只实现协变返回类型和方法 参数类型是不变的。
C#没有实现任何变量(所以两者都是不变的)。
There也是一个很好的段落,用于区分控制参数和“ left-over ”参数之间的参数。控制的是协变的,非控制的是逆变的。这是关于多个调度语言,虽然大多数情况下你指的是一种调度语言。但即使只有一个控制论点(self
/ this
)。
以下是段落(我没有时间研究paper it is referring to,如果您有时间并发布您的调查结果,请随时阅读):
Giuseppe Castagna [3]观察到,在具有多个调度的类型语言中,泛型函数可以有一些控制调度的参数和一些“ left-over “没有的论据。由于方法选择规则选择最具体的适用方法,如果方法覆盖另一个方法,则覆盖方法将具有更多特定类型的控制参数 。另一方面,为了确保类型安全,语言仍然必须要求 left-over 参数至少是一般的。使用前面的术语,用于运行时方法选择的类型是协变,而不用于方法的运行时方法选择的类型是逆变的。
像Java这样的传统单调度语言也遵循这个规则:只有一个参数用于方法选择(接收者对象,作为隐藏参数传递给方法
this
),实际上是this
在重写方法中比在超类中更专业。
根据该段我假设 self
论证的性质不是常规方法论证(可能是逆变),因为self
是另一种论点 - 控制论证 - 是协变的。
......即使我们刚刚确定,由于替代原则,被覆盖方法的论据需要是逆变的。
嗯,它看起来不是全部。