超类对象调用子类构造函数?这是如何工作的?

3
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的静态绑定时遇到了这段代码。我无法理解这一行代码:

superclass B = new subclass();

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


4
除了奇特的命名标准外,问题涉及实例和多态性,却出现了“静态”的上下文。这使得问题变得非常复杂。 - ernest_k
3
我们是否正在创建一个超类的对象并调用子类的构造函数?不是的,new subclass() 创建的是子类的对象,并将其分配给类型为 superclass 的变量,这意味着您只能使用该变量来调用在超类中声明的方法。 - Andreas
1个回答

3

在准备答案时,我发现我需要使用超类和子类这两个词有两个不同的意义。我将重新命名类为ThingCar,并将"超类"和"子类"这些词用于一般概念。

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类型的实例,始终如此。结果是[对]一个Car实例的引用。

现在,您可以将[对]Car实例的引用存储到允许Car实例的任何类型的变量中。这包括:

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

那么,对于这行代码会发生什么呢?

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

它创建一个新的Car实例,因此当然调用Car构造函数(*1)(*2)。然后它将对此实例的引用存储在变量B中,这允许所有类型的Thing实例,只要它们继承自Thing并且支持从Thing对象所期望的一切。在(*1)(*2)处发生了什么?
    B.print();

它调用了被B引用的实例的print()方法。由于该实例是一个Car实例,因此您将获得Car.print()结果,而不是Thing.print()
更多说明:
如果Car有一些在Thing中找不到的额外方法(例如drive()方法),编译器将不允许您在B上调用它们,因为并非所有Thing对象都拥有它们,只有一些专门的Thing版本(即Car版本)。
我建议您熟悉Java命名约定,例如类名始终以大写字母开头,变量以小写字母开头。Java程序员非常习惯这些约定,我们发现阅读不遵循这些规则的代码真的很困惑。
(*1) 在您的情况下,构造函数没有明确定义,但由Java编译器自动生成。
(*2) 子类构造函数始终调用其超类的构造函数,以及一直向上到Object构造函数,以初始化子类从其超类继承的所有方面的实例。

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