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

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

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

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

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

```java
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` , _также_ будут обладать этими свойствами!

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

![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [Код запуска](https://repl.it/CJXz/0)

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

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

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

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

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

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

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

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

```java
Vehicle car = new Car(); 
```

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

```java
Car car = new Vehicle(); // ERROR 
```

![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [Код запуска](https://repl.it/CJYB/0)

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

```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:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [Код запуска](https://repl.it/CJYM/0)

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

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

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

```java
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:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [Код запуска](https://repl.it/CJYZ/1)

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

**Примечания** :

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

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

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

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

```java
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:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [Код запуска](https://repl.it/CJY4/0)

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

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

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

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

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

Как упоминалось ранее, конструкторы не могут быть непосредственно унаследованы подклассом. Хотя подкласс _требуется_ для вызова конструктора своего родителя в качестве [первой операции](http://stackoverflow.com/questions/1168345/why-does-this-and-super-have-to-be-the-first-statement-in-a-constructor) в своем собственном конструкторе. Как? Вы догадались, используя `super` :

```java
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:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ": Ракета:") [Код запуска](https://repl.it/CJY8/0)

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

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

Поздравляю, теперь вы все знаете о Наследии! Подробнее о расширенных способах наследования вещей в абстрактных классах и [интерфейсах](//forum.freecodecamp.com/t/java-docs-interfaces) !