繁体   English   中英

为什么我的子类对象在向上转型时使用父类变量而不是方法?

[英]Why does my child class object use the parent classes variable but not methods when upcasting?

为什么“beagle”使用 speak() 的“Dog”执行但使用 Animal 类 legs 变量(似乎不一致)? 如果我只创建 2 个对象,为什么构造函数每次运行两次? (见下面的输出)

这最初是一个向上转型/向下转型的例子,所以我试图改变对象的类型,也就是 Animal dog = new Dog(); 而不是 Dog dog = new Dog();

而在Animal dog = new Dog()中,“Animal”代表什么,Dog()又代表什么? (我相信一个是对象类型)

// Online Java Compiler
// Use this editor to write, compile and run your Java code online

class Animal {
    int legs;

    Animal(){
        //this.legs = 5;
        System.out.println("-- Animal Constructor called --");
    }

    void speak(){
        System.out.println("Speak!");
    }
}

class Dog extends Animal {

    int legs;

    Dog(){
        this.legs = 4;
        System.out.println("-- Dog Constructor called --");
    }
    void speak(){
        System.out.println("Bow wow!");
    }
}

class Main {
    public static void main(String[] args) {

        Animal beagle = new Dog();
        Dog chew_wawa = new Dog();
//        Animal animal = new Animal();


        System.out.println(beagle.legs);
        System.out.println(chew_wawa.legs);
//        System.out.println(animal.legs);


        beagle.speak();
        chew_wawa.speak();
//        animal.speak();
    }

}

为什么这段代码的输出是:

-- Animal Constructor called --
-- Dog Constructor called --
-- Animal Constructor called --
-- Dog Constructor called --
0
4
Bow wow!
Bow wow!

Process finished with exit code 0

当您创建子类(例如Dog )的对象并将其分配给超类引用(例如Animal )时,您就是在向上转换该对象。 向上转型允许您将子类的对象视为超类的对象。 在这种情况下,当您调用 beagle 对象的speak()方法时,它将使用 Dog 类中speak()方法的实现,因为那是该对象的实际类型。 但是,当您访问beagle对象的legs变量时,它将使用Animal类中定义的legs变量的值,因为那是引用变量的类型。

 public static void main(String[] args) {
    // Upcasting: creating a Dog object and assigning it to an Animal reference
    Animal beagle = new Dog();

    // Downcasting: casting the Animal reference back to a Dog reference
    Dog chew_wawa = (Dog)beagle;
    
    // Continue with the print statements...
}
  1. 如果我只创建 2 个对象,为什么构造函数每次运行两次?

Java 添加 super(); 在每个调用父类构造函数的构造函数的第一行——在你的例子中是 Animal()。 所以无论何时,你为一个类创建一个对象,它的父类构造函数将首先被调用,然后是子类构造函数。

  1. 为什么“beagle”使用speak()的“Dog”执行方式?

在 Java 中,对象创建发生在堆内存中。 对于 Animal animal = new Dog(); animal 是一个引用类型和 new Dog(); 是在堆中分配内存的对象。 beagle 使用 speak() 的 Dog 版本,因为该动物引用 Dog 对象,因此调用 Dog 版本。 这个概念被称为多态性在此处输入图像描述

  1. 但是使用 Animal 类 legs 变量(似乎不一致)?

animal 引用类型引用 Dog() 对象,它具有变量(腿)的父版本和子版本。 使用哪个版本取决于参考类型(在您的情况下为动物)。 这个概念叫做变量隐藏

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM