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

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

Зачем это нужно?

Основная задача механизма наследования - избежать дублирования кода. Взглянем на пример:

В файле Cat.java

public class Cat { // Класс описывающий котика private String nickname; // Кличка животного private int age; // Возраст private String breed; // Порода public Cat(String nickname, int age, String breed) { // Конструктор this.nickname = nickname; this.age = age; this.breed = breed; } /* Перечисляем геттеры и сеттеры... */ public String getNickname() { return nickname; } //итд... /* Реализуем другие методы */ public void run(){ System.out.println(this.nickname+" побежал(а)"); } // итд... }

В файле Bird.java

public class Bird { // Класс описывающий птицу private String nickname; // Кличка животного private int age; // Возраст private String breed; // Порода public Cat(String nickname, int age, String breed) { // Конструктор this.nickname = nickname; this.age = age; this.breed = breed; } /* Перечисляем геттеры и сеттеры... */ public String getNickname() { return nickname; } //итд... /* Реализуем другие методы */ public void run(){ System.out.println(this.nickname+" побежал(а)"); } public void fly(){ System.out.println(this.nickname+" полетел(а)"); } // итд... }

Вот мы написали два класса Car.java и Bird.java, а чем они отличаются?

Почти ничем, кроме того, что птица ещё умеет летать, а коту мы можем добавить ещё какие-то методы, например орать под окнами.

Кроме котов и птиц, мы можем создать приложение зоопарк, где у нас будут десятки животных, у всех животных будут примерно одинаковые поля и методы.
В итоге, описывая каждого животного, нам придётся написать довольно много повторяющегося кода...

А что если мы создадим общий класс Animal.java, запишем в нём основные поля и методы, которые подходят для всех животных. В классах животных укажем лишь то, чем они отличаются.
В итоге мы получим родительский класс Animal.java и классы животных которые от него наследуются, т.е. имеют те же поля и методы, что и родительский класс.

В файле Animal.java

public class Animal { // Класс описывающий животного private String nickname; // Кличка животного private int age; // Возраст private String breed; // Порода public Animal(String nickname, int age, String breed) { // Конструктор this.nickname = nickname; this.age = age; this.breed = breed; } /* Перечисляем геттеры и сеттеры... */ public String getNickname() { return nickname; } //итд... /* Реализуем другие методы */ public void run(){ System.out.println(this.nickname+" побежал(а)"); } // итд... }

В файле Cat.java

public class Cat extends Animal { public Cat(String nickname, int age, String breed) { super(nickname, age, breed); } }

В файле Bird.java

public class Bird extends Animal { public Cat(String nickname, int age, String breed) { super(nickname, age, breed); } public void fly(){ System.out.println(this.nickname+" полетел(а)"); } }

Обратите внимание на сколько сократился код. И при этом вы можете запросто вызывать метод run(), и у котика, и у птички, и у других животных, которые будут наследоваться от класса Animal.

Функция super(), которая находится в конструкторе, это вызов родительского конструктора, после этой функции вы можете назначить другие поля, если есть такая необходимость.

Ключевое слово extends

В переводе с англ. слово extends переводится как расширяется.

В контексте программирования более правильно говорить, что дочерний класс расширяет родительский класс. Т.е. добавляет родительскому классу функциональности.
Однако, в русскоговорящем обществе, больше прижился термин наследование.

Предположим, что мы используем библиотку для работы с базой данных, и там имеется класс, который умеет посылать основные запросы к БД.

Файл библиотеки для работы с БД

public class DataBase{ public DataBase() {} public void getRowById(String tableName, int id){ // запрос к БД для получения строки по идентификатору } public void getRows(String tableName){ // запрос к БД для получения всех строк таблицы } public void insertRow(String tableName, String[] rows, String[] values){ // запрос к БД для добавления записи } }

Итак, мы имеем класс DataBase.java который для нас любезно кто-то разработал. Мы его активно используем для работы с БД.
И в один прекрасный момент, нам требуется выполнить удаление записи из базы данных. Но, в классе DataBase.java нет метода, который позволил бы это сделать.
Как теперь быть?

Ответ прост, мы воспользуемся механизмом наследования и расширим функциональность этого класса. Например вот так:

Класс расширяющий возможности DataBase.java

public class MyDataBase extends DataBase{ public MyDataBase() {} public void deleteRowById(String tableName, int id){ // запрос к БД для удаления строки по идентификатору } }

В итоге, создав объект от класса MyDataBase.java мы можем вызывать те методы которые были в DataBase.java и дополнительно, мы реализовали недостающий нам функционал. Удобно получается, не так ли? Пользуйтесь на здоровье)


Мы рассмотрели понятие наследования и его роль в объектно-ориентированном программировании.
Наследование — мощный инструмент для создания гибких, расширяемых и структурированных приложений.


Комментарии

Добавить комментарий

Чтобы оставить комменатрий необходимо Авторизоваться