Java 遗传的微妙之处

Java 遗传的微妙之处,java,inheritance,polymorphism,super,Java,Inheritance,Polymorphism,Super,假设SList是TailList的super类 如果我执行以下代码 SList s; TailList t = new TailList(); s = t; 这与执行SList s=new TailList()相同 现在,静态类型的t仍然是TailList?对象将被实例化为TailList,赋值不会改变这一点。(如果该语言能够在赋值时更改实现类,那将是一个巧妙的技巧;) 例如,你总是可以去 TailList t = new TailList(); Object o = t; 这是否更清楚?对

假设
SList
TailList
super类

如果我执行以下代码

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


现在,静态类型的t仍然是
TailList

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

例如,你总是可以去

TailList t = new TailList();
Object o = t;
这是否更清楚?对象仍然是同一个实现类。它不会变成一个对象,即使我们以这种方式引用它

您可以始终执行System.err.println(s.getClass().getName())并查看


顺便说一句,这实际上是多态性而不是继承,因为您将对象作为层次结构中更高的类引用。如果调用
t.slistMethod()
而不重写它,则继承将是无效的。

对象将被实例化为
尾列表
,赋值不会改变这一点。(如果该语言能够在赋值时更改实现类,那将是一个巧妙的技巧;)

例如,你总是可以去

TailList t = new TailList();
Object o = t;
这是否更清楚?对象仍然是同一个实现类。它不会变成一个对象,即使我们以这种方式引用它

您可以始终执行System.err.println(s.getClass().getName())并查看


顺便说一句,这实际上是多态性而不是继承,因为您将对象作为层次结构中更高的类引用。如果调用
t.slistMethod()
而不重写它,则继承将是无效的。

当执行
SList s=new TailList()时,发生的情况如下:

  • 调用
    new TailList()
    ,创建运行
    TailList
    构造函数的新对象。当构造函数完成时,将返回一个匿名的
    TailList
    引用
  • 匿名
    TailList
    引用被分配给
    s
  • 由于
    TailList
    继承自
    SList
    ,因此您也可以通过它来引用它。对对象的引用不会更改对象本身

    想象一下,我把一个垃圾桶放在某个地方,然后告诉不知道那个物体是垃圾桶的人,我在那个地方放了一个“容器”。垃圾箱确实是一个容器,但那个人只知道它是一个容器。这并不能改变它是一个垃圾箱的事实,但另一个人不能安全地假设他可以把垃圾放在那里,或者垃圾随时都会被清空,因此他不知道在他所指的“容器”上调用此功能

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

    String s = "Hello there";
    Object o = s;
    
    o
    现在指的是字符串对象,但将其视为“对象”,它不知道它是否有长度,或者它是否包含字符,即使它知道

    另一方面,
    s
    在仍然引用
    o
    所引用的同一对象时,知道该对象是
    字符串
    ,并且可以在该对象上使用
    字符串
    功能

    如果我们愿意,我们可以假设
    o
    是一个
    String
    ,通过一种称为“casting”的机制:

    现在,我们将
    o
    引用的对象称为
    字符串
    。所有这些对对象本身没有任何改变,只是引用的改变。就好像,在前面的类比中,被告知神秘“容器”的人会假定容器更确切地说是一个“垃圾桶”。我们也可能做出错误的假设,即容器是一个包装容器

    Integer i = (Integer)o; // throws ClassCastException
    
    幸运的是,当我们在Java中错误地假设时,我们会得到一个
    ClassCastException
    ,这与现实生活中的情况不同,在现实生活中,如果您将物品放入垃圾箱,同时将其称为包装容器,您的物品将被扔进垃圾箱

    或者,让你困惑的是第一个作业。嗯,
    newtaillist()
    部分
    slists=newtaillist()
    本身是对
    TailList
    构造函数的静态调用,它将始终返回
    TailList
    引用。随后的赋值仍将引用调用构造的
    TailList
    对象


    TL;博士


    是的,这是一样的。

    当您执行
    SList s=new TailList()时,发生的情况如下:

  • 调用
    new TailList()
    ,创建运行
    TailList
    构造函数的新对象。当构造函数完成时,将返回一个匿名的
    TailList
    引用
  • 匿名
    TailList
    引用被分配给
    s
  • 由于
    TailList
    继承自
    SList
    ,因此您也可以通过它来引用它。对对象的引用不会更改对象本身

    想象一下,我把一个垃圾桶放在某个地方,然后告诉不知道那个物体是垃圾桶的人,我在那个地方放了一个“容器”。垃圾箱确实是一个容器,但那个人只知道它是一个容器。这并不能改变它是一个垃圾箱的事实,但另一个人不能安全地假设他可以把垃圾放在那里,或者垃圾随时都会被清空,因此他不知道在他所指的“容器”上调用此功能

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

    String s = "Hello there";
    Object o = s;
    
    o
    现在指的是字符串对象,但将其视为“对象”,它不知道它是否有长度,或者它是否包含字符,即使它知道

    另一方面,
    s
    在仍然引用
    o
    所引用的相同对象时,知道
    SList s = new TailList();