父类对象调用子类构造函数?如何运作?

时间:2019-01-11 16:30:18

标签: java static polymorphism

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(); 
    } 
} 

我在学习static binding from geeksforgeeks时遇到了这段代码。我无法理解这一行:

  

超类B =新的subclass();

不确定如何运行。基本上,我们是否要创建超类的对象并调用子类的构造函数?这对我来说没有多大意义,因为我一直都看过并且习惯于A obj = new obj();类型的对象创建。

1 个答案:

答案 0 :(得分:1)

在准备答案时,我发现必须以两种不同的含义来使用超类和子类。我将这些类重命名为ThingCar,并在常规概念中使用单词“ superclass”和“ subclass”。

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个对象。

那会发生什么

    B.print();

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

更多说明:

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

而且我建议您习惯Java命名约定,例如类名始终以大写字母开头,变量始终以小写字母开头。 Java专家已经习惯了这些约定,因此我们发现读取不遵循这些规则的代码确实令人困惑。

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

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