首页 > 解决方案 > 调用子类构造函数的超类对象?这是如何运作的?

问题描述

public class NewClass 
{ 
    public static class superclass 
    { 
        static void print() 
        { 
            System.out.println("print in superclass."); 
        } 
    } 
    public static class subclass extends superclass 
    { 
        static void print() 
        { 
            System.out.println("print in subclass."); 
        } 
    } 

    public static void main(String[] args) 
    { 
        superclass A = new superclass(); 
        superclass B = new subclass(); //This line?
        A.print(); 
        B.print(); 
    } 
} 

我在从 geeksforgeeks学习静态绑定时遇到了这段代码。我无法理解这一特定行:

超类 B = 新子类();

不知道这是如何工作的。基本上,我们是在创建超类的对象并调用子类的构造函数吗?这对我来说没有多大意义,因为我一直看到并习惯于:A obj = new obj();键入对象创建。

标签: javastaticpolymorphism

解决方案


在准备我的答案时,我发现我必须以两种不同的含义使用超类和子类这两个词。我会将这些类重命名为ThingandCar并使用“超类”和“子类”来表示一般概念。

public class NewClass 
{ 
    public static class Thing
    { 
        static void print() 
        { 
            System.out.println("print in superclass."); 
        } 
    } 
    public static class Car extends Thing
    { 
        static void print() 
        { 
            System.out.println("print in subclass."); 
        } 
    } 

    public static void main(String[] args) 
    { 
        Thing A = new Thing(); 
        Thing B = new Car(); //This line?
        A.print(); 
        B.print(); 
    } 
}

表达式new Car()总是创建类型的实例Car。总是。结果是 [a reference to] 的一个实例Car

现在,您可以将 [a reference to] 的实例存储到Car允许实例的任何类型的变量中Car。那就是:

  • 一个Car类型的变量,
  • 使用任何超类声明的变量Car(并且与Thing B声明匹配),
  • 直接或间接实现的接口类型声明的变量Car

那么,这行代码会发生什么

    Thing B = new Car(); //This line?

它创建了一个新Car实例,因此当然会调用Car构造函数 (*1) (*2)。然后它将对该实例的引用存储在变量B中,这允许所有类型的Thing实例,只要它们继承自Thing并因此支持对象所期望的所有内容Thing

发生了什么

    B.print();

它调用由print()引用的实例的方法B。由于该实例是一个Car实例,因此您会得到Car.print()结果,而不是Thing.print().

还有一些说明:

如果在(例如方法)Car中找不到一些其他方法,编译器将不允许您在 上调用它们,因为并非所有对象都有它们,而只有一些专门的版本(即那些)。Thingdrive()BThingThingCar

我建议习惯 Java 命名约定,例如类名总是以大写字母开头,变量以小写字母开头。Java 人非常习惯这些约定,以至于我们发现阅读不遵循这些规则的代码真的很困惑。

(*1) 在您的情况下,构造函数没有明确定义,而是由 Java 编译器自动生成。

(*2) 子类构造函数总是调用其超类的构造函数,以此类推直到Object构造函数,以初始化子类从其超类继承的实例的所有方面。


推荐阅读