子类型和超类型,方法和转换

时间:2015-01-14 15:23:50

标签: java methods type-conversion implicit-conversion

我目前正在阅读Barbara Liskov第二版的非常好的 Java程序开发:抽象,规范和面向对象设计(2000),用于研究生课程。作为参考,我对于这个问题,请参阅第2.4.2节:转换和重载(第27-29页)。 Liskov正在讨论方法重载以及Liskov称编译器识别"'最具体的'" (第28页)为超载呼叫提供实际参数时的方法。

这里的示例Liskov提供了以下重载方法foo

void foo (T a, int x) // defn. 1
void foo (S b, long y) // defn. 2

接下来的电话 - 利斯科夫声称​​不合法

o.foo(e, 3)

以下是我们对实际参数的了解:

  1. S是T的子类型。
  2. 参数eS
  3. 类型的变量

    在我看来,理论上这是一个合法的呼吁。调用o.foo(e, 3)与使调用更具体相同(如果我在比较表观类型时考虑编译器):

    o.foo((T) e, 3)

    显然,e只能在进行此调用时访问超类型的减少的常见行为;但是,它还不是一个合法的电话吗?

    规模较小:

    Object o = s是合法的s评估类型String(仅仅是为了引用:Liskov,第26页)。

    为什么我错了?我不理解的是什么?

1 个答案:

答案 0 :(得分:0)

所以,我向我的计算机科学伙伴展示了这个问题。而且,现在我知道了答案,我觉得自己像个假人(他问我这个问题,"是的,它是合法的;但是,编译器如何知道要调用哪种方法?" );然而 - 现在我已经拥有了我的噢,呃!'那一刻 - 我认为答案仍然会对那些暂时陷入我所处位置的人有所帮助:

在这里,问题不在于呼叫的合法性(//defn. 1是唯一可用的方法,呼叫绝对合法)。这是一个问题 - 如上面的问题中所述 - "最具体的"对象e不是问题。

类型3的实际参数int是问题所在。

为什么呢? int合法扩展为long;因此,编译器不知道调用哪个方法,因为两个调用都可以接收这些实际参数。