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

192 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
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) !