Объект суперкласса, вызывающий конструктор подкласса? Как это работает? - PullRequest
0 голосов
/ 11 января 2019
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(); создание типа объекта.

1 Ответ

0 голосов
/ 11 января 2019

При подготовке своего ответа я обнаружил, что мне пришлось использовать слова суперкласс и подкласс в двух разных значениях. Я переименую классы в Thing и Car и буду использовать слова «суперкласс» и «подкласс» для общих понятий.

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 экземпляры. И это:

  • a 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 имел некоторые дополнительные методы, не найденные в Thing (например, метод drive()), компилятор не позволил бы вам вызывать их на B, так как не все объекты Thing имеют их , но только некоторые специализированные Thing версии (т.е. Car).

И я рекомендую привыкнуть к соглашениям об именах Java, например, что имена классов всегда начинаются с заглавной буквы, а переменные с нижнего регистра. Ребята из Java настолько привыкли к этим соглашениям, что мы находим действительно запутанным чтение кода, который не следует этим правилам.

(* 1) В вашем случае конструктор не определен явно, но автоматически генерируется компилятором Java.

(* 2) Конструктор подкласса всегда вызывает конструктор своего суперкласса и т. Д. Вплоть до конструктора Object, чтобы инициализировать все аспекты экземпляра, который подкласс наследует от своего суперкласса.

...