继承的微妙之处

时间:2014-02-23 09:34:00

标签: java inheritance polymorphism super

假设SListsuper class的{​​{1}}。

如果我执行以下代码,

TailList

与执行SList s; TailList t = new TailList(); s = t; 相同吗?

现在,静态类型仍然是SList s = new TailList();

4 个答案:

答案 0 :(得分:1)

该对象将被实例化为TailList,并且赋值不会改变它。 (如果语言可以在赋值时更改实现类,那将是一个巧妙的技巧;))

例如,你总是可以去

TailList t = new TailList();
Object o = t;

这会让它更清楚吗?该对象仍然是相同的实现类。它不会改变为Object,即使我们以这种方式引用它。

你总是可以做一个System.err.println(s.getClass()。getName())并看看。

实际上,这实际上是多态而不是继承,因为您将对象引用为层次结构中较高的类。如果您在不覆盖它的情况下调用t.slistMethod(),则继承。

答案 1 :(得分:1)

执行SList s = new TailList();时,会发生以下情况:

    调用
  1. new TailList(),创建一个运行TailList构造函数的新对象。构造函数完成后,将返回匿名TailList引用。
  2. 匿名TailList引用已分配给s
  3. 由于TailList继承自SList,您也可以通过它来引用它。对象的引用不会改变对象本身。

    想象一下,我把垃圾桶放在某个地方,然后告诉那些不知道该物体的人是垃圾桶,我在那个位置放了一个“容器”。垃圾桶确实是一个容器,但那个人只知道它是一个容器。这并没有改变它是垃圾桶的事实,但另一个人不能安全地认为他可以把垃圾放在那里,或者计划在任何时候清空,因此他不会知道要调用这个功能在他所指的“容器”上。

    例如,假设我们有以下代码:

    String s = "Hello there";
    Object o = s;
    

    o现在引用一个String对象,但是它将它视为一个“对象”,它不知道它有一个长度,或者它包含字符,即使它确实存在。

    另一方面,

    s虽然仍在引用o引用的同一对象,但知道此对象是String,并且可以使用String该对象的功能。

    如果我们愿意,我们可以假设o是一个名为“cast”的机制String

    String s2 = (String)o;
    

    我们现在将o引用的对象称为String。所有这一切都没有改变对象本身,它只是参考的一个变化。好像,对于前一个类比,被告知神秘“容器”的人会认为容器更具体地是“垃圾桶”。我们也可以做出错误的假设,即容器是一个包装容器

    Integer i = (Integer)o; // throws ClassCastException
    

    幸运的是,当我们在Java中错误地假设时,我们会得到一个ClassCastException,与现实生活中不同的是,如果您将物品放入垃圾箱,同时将其作为包装容器引用,您的物品将被扔到垃圾箱中

    或许,令你困惑的是第一次任务。好吧,new TailList()的{​​{1}}部分本身是SList s = new TailList();的构造函数的静态调用,它将始终返回TailList引用。之后的赋值仍将引用由调用构造的TailList对象。


    TL; DR

    是的,这是一回事。

答案 2 :(得分:1)

在静态类型的面向对象语言中,对象和变量都有关联的类型。

变量的类型('静态类型')由程序员在声明变量时指定。它永远不会改变。

变量引用的对象类型('运行时类型')必须是变量声明类型的相同或子类型。对象永远不会更改类型,但可以为变量分配不同类型的不同对象。

第一个代码段声明了两个变量,类型为s的{​​{1}}和SList类型的t。它创建了一个TailList类型的对象,并在两个变量中存储对它的引用。

第二个代码段声明了TailList类型的变量s,创建了SList类型的对象,并在TailList中存储了对它的引用。

两种情况下的最终结果是s包含对s类型对象的引用。不同之处在于,在第一个片段中,存在变量TailList中存储的对象的附加引用(其仍具有静态类型t)。

答案 3 :(得分:1)

TailList t = new TailList();
SList s = t;

相同
SList s = new TailList();

是的,除了没有对新对象保持类型TailList的单独引用,因此您只能访问SList中的方法(除非您投射)。