超类引用子类对象

3
我感到困惑:我从一个学习资源中摘取了下面这些引用(带有它们所在章节的标题),但是这些引用似乎互相矛盾。

超类引用和子类对象

"决定可以访问哪些成员的是引用变量的类型,而不是它所引用的对象的类型"

覆盖方法支持多态

"确定执行哪个覆盖方法的版本的是被引用对象的类型,而不是引用变量的类型"

如果能对此进行澄清,将不胜感激。


好奇问一下...你从哪里得到这些的? - Anubian Noob
可能是Java - 引用变量的重复问题。 - Jayan
你的问题部分是重复的:https://dev59.com/dkzSa4cB1Zd3GeqPpL5x - Jayan
这并不完全是那个问题的重复。我认为它增加了更多内容。 - Anubian Noob
@Jayan - 这不是重复的问题。相反,这个问题纯粹是关于多态性的。 - Software Engineer
4个回答

2
假设我们有两个类。
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类的实例。


1
请看下面的程序。
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的Complete reference中获得上述两个语句的含义。

0
如果classB继承自ClassA并且你有:

ClassA a = new ClassB ();

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

然而,调用在ClassB中覆盖的ClassA方法将执行ClassB方法。


谢谢大家,我现在有更好的理解了。Anubian Noob,这些引用来自一本教科书,其中大部分我觉得很容易理解。 - danger mouse

0

超类引用和子类对象

假设Child继承自Parent,让我们看一下这个例子:

Parent obj = new Child();

现在,如果我们尝试使用obj,我们只能使用父类中指定的行为(方法)。我们无法使用来自子类的任何新方法。
但是,假设父类和子类都有一个方法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

因此,您只能通过引用它的类(第一个片段中的Parent)访问该类中的方法。但是,如果您已在实例化为的类(第一个片段中的Child)中覆盖了它,并在子类中重写了父类中的方法,则调用父类中存在的方法将调用在子类中重写的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接