freeCodeCamp/guide/russian/java/inheritance/index.md

12 KiB
Raw Blame History

title localeTitle
Inheritance наследование

наследование

Наследование Java относится к способности класса Java inherit свойства другого класса. Подумайте об этом, как о ребенке, наследующем свойства от своих родителей, концепция очень похожа на это. В Java lingo он также называется расширением класса. Некоторые простые вещи, которые нужно запомнить:

  • Класс, который распространяется или наследуется, называется подклассом
  • Класс, который расширяется или унаследован, называется суперклассом

Таким образом, наследование дает Java отличную возможность повторного использования кода или обмена кодами между классами!

Давайте опишем его с классическим примером класса Vehicle класса Car :

public class Vehicle { 
    public void start() { 
        // starting the engine 
    } 
 
    public void stop() { 
        // stopping the engine 
    } 
 } 
 
 public class Car extends Vehicle { 
    int numberOfSeats = 4; 
 
    public int getNumberOfSeats() { 
        return numberOfSeats; 
    } 
 } 

Здесь мы можем увидеть класс Car наследующий свойства класса Vehicle . Таким образом, нам не нужно писать один и тот же код для методов start() и stop() для Car , так как эти свойства доступны из его родительского или суперкласса. Поэтому объекты, созданные из класса Car , также будут обладать этими свойствами!

Car tesla = new Car(); 
 
 tesla.start(); 
 
 tesla.stop(); 

:rocket: Код запуска

Но имеет ли родительский класс методы для ребенка? Нет, нет.

Следовательно, всякий раз, когда вам нужно разделить некоторые общие части кода между несколькими классами, всегда полезно иметь родительский класс, а затем распространять этот класс всякий раз, когда это необходимо! Сокращает количество строк кода, делает код модульным и упрощает тестирование.

Что можно унаследовать?

  • Все protected и public поля и методы от родительских

Что нельзя унаследовать?

  • private поля и методы
  • Конструкторы. Хотя конструктор подкласса должен вызывать конструктор суперкласса, если он определен (подробнее об этом позже!)
  • Несколько классов. Java поддерживает только одно наследование , то есть вы можете наследовать только один класс за раз.
  • Поля. Отдельные поля класса не могут быть переопределены подклассом.

Тип литья и ссылки

В Java можно ссылаться на подкласс как экземпляр его суперкласса. Он называется полиморфизмом в объектно-ориентированном программировании (ООП), возможностью для объекта принимать различные формы. Например, объект класса Car можно называть экземпляром класса Vehicle следующим образом:

Vehicle car = new Car(); 

Хотя, наоборот, невозможно:

Car car = new Vehicle(); // ERROR 

:rocket: Код запуска

Поскольку вы можете ссылаться на подкласс Java как экземпляр суперкласса, вы можете легко передать экземпляр объекта подкласса в экземпляр суперкласса. Можно включить объект суперкласса в тип подкласса, но только если объект действительно является экземпляром подкласса . Поэтому имейте это в виду:

Car car = new Car(); 
 Vehicle vehicle = car; // upcasting 
 Car car2 = (Car)vechile; //downcasting 
 
 Bike bike = new Bike(); // say Bike is also a subclass of Vehicle 
 Vehicle v = bike; // upcasting, no problem here. 
 Car car3 = (Car)bike; // Compilation Error : as bike is NOT a instance of Car 

:rocket: Код запуска

Теперь вы знаете, как делиться кодом через отношения родитель-ребенок. Но что, если вам не нравится реализация определенного метода в дочернем классе и хотите написать для него новый? Что вы делаете тогда?

Переопределите это!

Java позволяет вам переопределять или переопределять методы, определенные в суперклассе. Например, ваш класс Car имеет другую реализацию start() чем исходный Vehicle , поэтому вы делаете это:

public class Vehicle { 
    public void start() { 
      System.out.println("Vehicle start code"); 
    } 
 } 
 
 public class Car extends Vehicle { 
    public void start() { 
      System.out.println("Car start code"); 
  } 
 } 
 
 Car car = new Car(); 
 car.start(); // "Car start code" 

:rocket: Код запуска

Таким образом, довольно просто переопределить методы в подклассе. Хотя, есть улов . Только этот метод суперкласса с той же сигнатурой метода, что и метод подкласса, будет переопределен. Это означает, что определение метода подкласса должно иметь одно и то же имя, одинаковое количество и тип параметров и в той же последовательности. Таким образом, public void start(String key) не будет отменять public void start() .

Примечания :

  • Вы не можете переопределить частные методы суперкласса. (Совершенно очевидно, не так ли?)
  • Что делать, если метод суперкласса, который вы переопределяете в подклассе, внезапно исчезает или меняются методы? Это не сработает во время выполнения! Поэтому Java предоставляет вам замечательную аннотацию @Override которую вы можете разместить над методом подкласса, который будет предупреждать компилятор об этих инцидентах!

Аннотации на Java - хорошая практика кодирования, но они не являются необходимостью. Компилятор достаточно умен, чтобы разобраться в себе. В отличие от других языков ООП, аннотации в Java не обязательно изменят метод или добавляют дополнительные функции.

Как назвать методы суперкласса?

Забавно, что вы спрашиваете об этом! Просто используйте ключевое слово super :

public class Vehicle() { 
    public void start() { 
      System.out.println("Vehicle start code"); 
    } 
 } 
 
 public class Car extends Vehicle { 
    public void run() { 
      super.start(); 
  } 
 } 
 
 Car car = new Car(); 
 car.run(); // "Vehicle start code" 

:rocket: Код запуска

NB : Хотя вы можете вызвать родительский метод, используя super , вы не можете подойти к иерархии наследования с помощью прикованных super вызовов.

Как узнать тип класса?

Использование ключевого слова instanceof . Обладая множеством классов и подклассов, было бы немного смутно знать, какой класс является подклассом, из которых один во время выполнения. Таким образом, мы можем использовать instanceof для определения того, является ли объект экземпляром класса, экземпляром подкласса или экземпляром интерфейса.

Car car = new Car(); 
 
 boolean flag = car instanceof Vehicle; // true in this case! 

Конструкторы и наследование

Как упоминалось ранее, конструкторы не могут быть непосредственно унаследованы подклассом. Хотя подкласс требуется для вызова конструктора своего родителя в качестве первой операции в своем собственном конструкторе. Как? Вы догадались, используя super :

public class Vehicle { 
    public Vehicle() { 
        // constructor 
    } 
    public void start() { 
      System.out.println("Vehicle start code"); 
    } 
 } 
 
 public class Car extends Vehicle { 
    public Car() { 
      super(); 
    } 
    public void run() { 
      super.start(); 
  } 
 } 

:rocket: Код запуска

Помните, что если суперкласс не имеет определенных конструкторов, вам не нужно его явно указывать в подклассе. Java обрабатывает это внутренне для вас! Вызов в super выполняется в случае, когда суперкласс должен вызываться с любым другим конструктором, отличным от конструктора по умолчанию .

Если никакие другие конструкторы не определены, то Java вызывает конструктор суперкласса по умолчанию ( даже если он явно не определен ).

Поздравляю, теперь вы все знаете о Наследии! Подробнее о расширенных способах наследования вещей в абстрактных классах и интерфейсах !