简体   繁体   中英

Super class object invoking a subclass constructor? How does that work?

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

I came across this code while learning static binding from geeksforgeeks . I am unable to understand this particular line:

superclass B = new subclass();

Not sure how this works. Basically, are we creating an object of super class and invoking the subclass' constructor? That doesn't make much sense to me because I have always seen and am used to : A obj = new obj(); type object creation.

While preparing my answer, I found that I had to use the words superclass and subclass in two different meanings. I'll rename the classes to be Thing and Car and use the words "superclass" and "subclass" for the general concepts.

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

An expression new Car() always creates an instance of type Car . Always. And the result is [a reference to] an instance of Car .

Now, you can store [a reference to] an instance of Car into a variable of any type that allows for Car instances. And that is:

  • a Car -typed variable,
  • a variable declared with any superclass of Car (and this matches a Thing B declaration),
  • a variable declared with an interface type directly or indirectly implemented by Car .

So, what happens with the line of code

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

It creates a new Car instance, and therefore of course invokes the Car constructor (*1) (*2). And then it stores a reference to this instance in the variable B , which allows for all kinds of Thing instances as long as they inherit from Thing and thus support everything that is expected from a Thing object.

And what happens at

    B.print();

It calls the print() method of the instance that's referenced by B . And as that instance is a Car instance, you get the Car.print() results, not the Thing.print() .

Some more remarks:

If Car had some additional methods not found in Thing (eg a drive() method), the compiler wouldn't allow you to call them on B , as not all Thing objects have them, but only some specialized Thing versions (ie the Car ones).

And I recommend to get used to the Java naming conventions, eg that classnames always begin with an upper-case letter and variables with lower-case. Java guys are so much used to these conventions that we find it really confusing to read code that doesn't follow these rules.

(*1) In your case the constructor is not explicitly defined, but auto-generated by the Java compiler.

(*2) A subclass constructor always calls the constructor of its superclass, and so on up to the Object constructor, to initialize all the aspects of the instance that the subclass inherits from its superclass.

Apologies, I'm pretty new to Java myself. Would you be able to provide instances where:

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

would be used over just creating a car object? Such as:

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

I guess what would be an example of an instance where you'd be creating an object by calling a constructor for a subclass, but not supporting all the methods. I'm a little confused how this could be valuable in practice?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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