【问题标题】:Dynamic Method Dispatch and inheritance动态方法分派和继承
【发布时间】:2013-07-14 06:14:39
【问题描述】:

我正在阅读一本 JAVA 书籍并遇到了 Dynamic Method Dispatch。但这对我来说有点困惑(也许是因为我是新手)。书上说它是基于一个原则:一个超类引用变量可以引用一个子类对象。

    class X{
    void display()
    {
       System.out.println("This is class X");
    }
    }

    class Y extends X{
    void display()
    {
        System.out.println("This is class Y");
    }
    void play()
    {
        System.out.println("PLAY!");
    }
    }

    class k{
    public static void main(String args[]){
    X obj1 = new X();
    Y obj2 = new Y();
    X ref  = new X();

    ref = obj1;
    ref.display();
    //output is :This is class X

    ref = obj2;   //Using the principle stated above
    ref.display();
    //output is :This is class Y

    ref.play();  //Compiler error:Play not found 
    //well it must be because ref is of X type and for X no methods of its subclass "Y"
    //is visible
    }
    }

所以我想问如果 玩() 不可见那为什么 展示() 的 Y 是可见的??

【问题讨论】:

  • ref 的类型为 X。因此,您只能访问class X 中定义的方法签名。

标签: java inheritance


【解决方案1】:

承诺的角度来考虑它。 X ref 承诺它所拥有的(如果有的话)是X 类型。当然,Y 也是X 类型,这就是子类化的意思:Y 的每个实例也是X 的一个实例(加上一些调整和额外功能)。但是,play 方法不能通过它调用,因为根据语言定义,内容不已知Y

您可以显式地将ref 转换为Y,然后在其上调用play

((Y) ref).play();

这是安全的,因为 Java 中的每个对象都知道自己的 real 类型。如果对象引用指向错误类型的实例(例如,obj1),您将在运行代码时得到ClassCastException。 (如果你知道 C,这完全不同。)

【讨论】:

    【解决方案2】:

    静态类型检查确保您只能调用那些属于引用的静态(声明的)类型的方法。这就是为什么你不能通过 X 类型的引用调用 .play() 的原因。

    然而,动态方法分派确保,如果一个方法在子类中被覆盖,那么该特定方法将被动态调用(在运行时)。

    【讨论】:

      【解决方案3】:

      父类引用包含从父对象继承的子对象的属性。因此,您可以从包含子对象的父引用中调用所有这些方法,这些方法由子类继承和覆盖。

      简而言之,引用将决定可以调用哪些方法,它所持有的对象将决定,将调用哪个方法(父/子类)。

      所以我想问如果 play() 不可见那么为什么 display() Y 可见??

      display 是可见的,因为这是 Parent 引用的一种方法。但是游戏属于独生子女,因此父母看不到。

      【讨论】:

        【解决方案4】:

        在执行之前,Java 程序由编译器处理。编译器确保只调用现有的方法。在上面的例子中,编译器只知道 ref 是声明的 X 类型,并且类型 X 没有方法 play 。它不会跟踪所有分配,也没有考虑到 ref 是由 Y 类型的 obj2 分配的——这种跟踪通常是不可能的情况,因为它可能取决于运行时数据,在编译时不可用。

        另一方面,运行时的方法调用依赖于实际类型,它可以是声明类型的扩展。由编译器发出的完全相同的代码可以调用方法 display 的不同实现,具体取决于变量 ref 引用的对象的实际类型。但是,编译器会检查方法 display 是否存在于所有可能分配给 ref 的对象类型。

        【讨论】:

          猜你喜欢
          • 2018-04-21
          • 1970-01-01
          • 2014-01-18
          • 1970-01-01
          • 2016-10-06
          • 1970-01-01
          • 2023-04-05
          • 2017-02-07
          • 2015-01-20
          相关资源
          最近更新 更多