Уроки модуля (1/2)
Наследование
Наследование — это фундаментальный механизм ООП, который позволяет классу (называемому дочерним классом или подклассом) наследовать поля и методы от другого класса (называемого родительским классом или суперклассом).
Это способствует повторному использованию кода и позволяет избежать ненужного повторения.
Расширение класса с помощью extends
В Java мы используем ключевое слово extends, чтобы указать, что класс наследуется от другого:
class Vehicle {
protected int speed; // 'protected' makes the field visible to subclasses
public void honk() {
System.out.println("Beep beep!");
}
}
class Car extends Vehicle {
// Car automatically inherits the speed field and the honk() method
}Конструктор и ключевое слово super()
Если у суперкласса есть конструктор, который принимает параметры, подкласс должен явно вызвать его в своем конструкторе, используя super(...) в качестве самого первого оператора:
class Person {
String name;
public Person(String name) {
this.name = name;
}
}
class Student extends Person {
int studentId;
public Student(String name, int studentId) {
super(name); // Invokes the constructor of Person
this.studentId = studentId;
}
}Переопределение метода (@Override)
Подкласс может предоставить собственную реализацию метода, унаследованного от суперкласса. Эта операция называется overriding (переопределение метода) и обозначается аннотацией @Override.
class Animal {
public void makeSound() {
System.out.println("Rumore generico");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Miao!");
}
}Модификатор protected
Модификатор доступа protected играет ключевую роль в наследовании. В отличие от private, который делает члены видимыми только внутри одного класса, protected разрешает доступ к полям и методам как внутри одного пакета, так и для всех подклассов, даже если они находятся в разных пакетах.
Доступ к родительским элементам с помощью super
Помимо вызова конструктора суперкласса, ключевое слово super можно использовать в методах подкласса для ссылки на методы или переменные родительского класса. Это особенно полезно, когда метод переопределен, но вы все равно хотите вызвать исходное родительское поведение:
class Animal {
public void sleep() {
System.out.println("Zzz");
}
}
class Cat extends Animal {
@Override
public void sleep() {
super.sleep(); // Executes the behavior of Animal
System.out.println("The cat purrs while sleeping.");
}
}Одиночное наследование в Java
В Java класс может расширять только один класс (одиночное наследование). Прямое наследование от нескольких классов (множественное наследование) не допускается; например, class Cat extends Animal, Mammal вызовет ошибку компиляции. Такой выбор конструкции позволяет избежать двусмысленности, известной как «проблема ромба» (когда два суперкласса определяют один и тот же метод с разными реализациями). Чтобы преодолеть это ограничение, в Java введена концепция Интерфейсов, которую мы рассмотрим в следующем модуле.
Попробуйте сами
Завершите подкласс Dog, расширив Animal. Объявите конструктор Dog, который принимает имя (String) и использует super(name) для передачи его конструктору Animal.
Показать подсказку
Напишите `public Dog(String name) { super(name); }` внутри класса Dog.
Решение доступно после 3 попыток
Расширьте Dog из Animal и переопределите метод makeSound(), чтобы он возвращал строку Woof вместо Generic Sound. Используйте аннотацию @Override.
Показать подсказку
Напишите `@Override` над объявлением `public String makeSound() { return 'Woof'; }` внутри Dog.
Решение доступно после 3 попыток
Объявите класс Cat, который расширяет Animal и переопределяет метод makeSound() для возврата строки Meow. Класс Animal уже имеет конструктор, принимающий имя; убедитесь, что конструктор Cat также принимает имя и правильно передает его конструктору суперкласса.
Показать подсказку
Создайте класс Cat, расширяющий класс Animal. Объявите конструктор `public Cat(String name) { super(name); }` и переопределить метод makeSound() с помощью @Override, чтобы вернуть Meow.
Решение доступно после 3 попыток