【问题标题】:Superclass references to subclass objects超类对子类对象的引用
【发布时间】:2015-01-06 04:22:48
【问题描述】:

我很困惑:我从学习资源中引用了以下引用(以及它们出现的部分的标题),但在我看来这些引用相互矛盾。

超类引用和子类对象

“是引用变量的类型——而不是它所引用的对象的类型——决定了哪些成员可以被访问”

重写方法支持多态

它是被引用对象的类型(不是引用变量的类型),它决定了将执行哪个版本的覆盖方法”

对此的任何澄清将不胜感激。

【问题讨论】:

标签: java inheritance reference polymorphism


【解决方案1】:

假设我们有两个类。

class Vehicle{
    
    public void drive(){
        System.out.println("Vehicle is Moving");
    }
}
class Car extends Vehicle{
    
    public void drive(){
        System.out.println("Car is Moving");
    }
    
    public void playMusic(){
        System.out.println("Car is Playing Music");
    }
}

“是引用变量的类型——而不是它所引用的对象的类型——决定了哪些成员可以被访问”

这意味着如果我们有这样的代码 Vehicle vehicle = new Car(); 使用vehicle对象,我们可以调用drive(),但不能调用playMusic(),因为vehicle的类型是Vehicle

“它是被引用对象的类型(而不是引用变量的类型),它决定了将执行哪个版本的覆盖方法”

这意味着如果我们有类似的代码

Vehicle vehicle = new Car();
vehicle.drive();

它将打印“Car is Moving”而不是“Vehicle is Moving”,因为存储在 vehicle 中的对象是 Car 的一个实例。

【讨论】:

    【解决方案2】:

    如果 classB 扩展 ClassA 并且你有:

    ClassA a = new ClassB ();
    

    使用a 变量,您只能访问ClassA 中定义的成员(或ClassA 的超类或ClassA 实现的接口)。您无法访问在ClassB 中定义但在ClassA 中未定义的成员(除非您将a 转换为ClassB)。

    但是,调用在 ClassB 中被覆盖的 ClassA 方法将执行 ClassB 方法。

    【讨论】:

    • 谢谢大家 - 我现在有了更好的理解。 Anubian Noob,引述来自教科书,我觉得其中大部分内容都很清楚。
    【解决方案3】:

    超类引用和子类对象

    假设 Child 扩展 Parent,让我们看看这个:

    Parent obj = new Child();
    

    现在如果我们尝试使用obj,我们只能使用父类中指定的行为(方法)。我们不能使用 Child 类的任何新方法。

    但是,假设 Parent 和 Child 都有一个方法 public String whoAmI()

    家长:

     return "Parent";
    

    孩子:

    return "Child";
    

    现在如果我们运行这段代码:

    Parent obj1 = new Child();
    Parent obj2 = new Parent();
    
    System.out.println(obj1.whoAmI());
    System.out.println(obj2.whoAmI());
    

    输出:

    Child
    Parent
    

    因此,您只能通过(第一个 sn-p 中的父级)访问您所引用的类中的方法。但是如果你在类中重写了它,它被实例化为(第一个 sn-p 中的子),并在子级中重写父级中的方法,然后调用父级中存在的方法将调用在孩子。

    【讨论】:

      【解决方案4】:

      看看下面的程序。

      class SuperMem{
          int i = 90;
          int j = 100;
      
          void show(){
              System.out.println("parent show..");
              System.out.println("Show inside Parent start");
              System.out.println(i + " " + j);
              System.out.println("Show inside Parent END");
          }
      }
      
      class submem extends SuperMem{
          int i = 10;
          int j = 20;
          void show(){
              System.out.println("Child show ..");
              System.out.println("Show inside Child start");
              System.out.println(i + " " + j);
              System.out.println("Show inside Child END");
      
          }
      }
      
      public class SuperMemDemo {
          public static void main(String[] args) {
              SuperMem m = new SuperMem();
              submem s = new submem();
              m = s;
      
              System.out.println("i " + m.i);
              System.out.println("j " + m.j);
              m.show();
          }
      
      }
      

      输出:

         i 90
         j 100
         Child show ..
         Show inside Child start
         10 20
         Show inside Child END
      

      方法是通过动态调度方法解决的,即在运行时。分析输出,您将从完整参考 Herbert Schildt 中了解上述两个语句的含义

      【讨论】:

        猜你喜欢
        • 2014-09-08
        • 2023-04-11
        • 2017-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-22
        • 2013-08-09
        • 1970-01-01
        相关资源
        最近更新 更多