【发布时间】:2018-07-07 15:21:37
【问题描述】:
我正在阅读的这本书刚刚介绍了包含、协变、逆变的概念及其对编程语言设计的影响。现在,在关于方法专业化的部分,我遇到了麻烦。
书中指出,当我们在子类中重写方法时,参数类型可能会被泛化,结果类型可能会被特化。然而,本书认为,对于没有被覆盖而是继承的方法,另一种类型的方法特化正在发挥作用,其中参数类型被特化,结果类型被泛化,因为我们可以将 self 关键字解释为参数:
“还有另一种形式的方法特化,它通过继承隐式发生。在 C 的方法中出现的 self 可以被认为是 C 类型,因为所有绑定到 self 的对象都具有 C 类型或 C 的子类型. 当 C 的方法被 C' 继承时,同样出现的 self 可以类似地被认为是类型 C'。因此 self 的类型默默地专门用于继承(协变!)。”
这是我的问题:我们不能将 self 关键字视为重写方法中的协变参数吗?然后我们最终会使用 this 关键字作为协变参数,即使我们刚刚确定,由于替换原则,重写方法的参数需要是逆变的。我忽略了什么吗?
感谢您的帮助!
【问题讨论】:
-
对不起,可能是我缺乏知识,但是“将self关键字视为协变参数”是什么意思?如果可能的话,也许我只需要一个例子。
-
如果你调用一个方法,你会隐式传递一个参数,即将self-keyword(有时称为this-keyword)绑定到该方法所属的对象。因此,像 myObj.m(arg1) 这样的方法可以等效地实现为函数 m(myObj, arg1) 。这就是 self 关键字可以解释为参数的原因。由于上述原因(第 3 段),该论点是协变的。
-
我有点好奇,您是否发现了有关此主题的更多信息,或者我在回答中所做的“研究”是否足够?
-
据我所知,现在不应将 this-arg 视为跨类中的方法及其在子类中的覆盖的协变,因为创建协变的动态是动态绑定。我的猜测是,答案与这样一个事实有关,即当两者之间存在覆盖时,来自继承方法的调用永远不能动态绑定到层次结构更上层的类的方法(除非你使用 super 关键字 I猜)。
-
包含和 self 关键字的两个概念似乎确实有些矛盾,所以你的答案是正确的!本书(A Theory of Objects by Abadi 和 Cardelli,如果您感兴趣的话)对此问题进行了一定的论述。它们可以通过不同的方式进行调和和平衡,例如特殊的 Self 返回类型,或者对包容的较弱定义。老实说,我想我不能告诉你答案,我想我自己也没有得出结论。我对这个话题很陌生,但我会继续挖掘 ;) 无论如何,谢谢你的帮助!
标签: oop covariance contravariance