- Создавать класс-наследник с помощью
extendsиsuper - Переопределять метод с аннотацией
@Override - Объяснять полиморфизм и проверять тип с помощью
instanceof
В компании работают обычные сотрудники и менеджеры. У всех есть имя и зарплата, но менеджер получает ещё и бонус. Вместо того чтобы писать класс Manager с нуля и повторять весь код Employee, можно сказать: «Менеджер — это тоже сотрудник, просто немного особенный». Для этого и существует наследование.
extends и super
Запись class Manager extends Employee означает, что Manager наследуется от Employee: подкласс (subclass) получает поля и методы суперкласса (superclass). Конструктор подкласса должен сначала вызвать конструктор родителя через super(...). А super.salary() вызывает родительскую версию метода.
public class Main {
public static void main(String[] args) {
Employee e = new Employee("Nigar", 1200);
Manager m = new Manager("Rashad", 2000, 500);
System.out.println(e.describe());
System.out.println(m.describe());
System.out.println(m.getName() + " earns " + m.salary());
}
}
class Employee {
protected String name;
protected double baseSalary;
Employee(String name, double baseSalary) {
this.name = name;
this.baseSalary = baseSalary;
}
String getName() { return name; }
double salary() { return baseSalary; }
String describe() {
return name + ": " + salary() + " AZN";
}
}
class Manager extends Employee {
private double bonus;
Manager(String name, double baseSalary, double bonus) {
super(name, baseSalary);
this.bonus = bonus;
}
@Override
double salary() {
return super.salary() + bonus;
}
}Nigar: 1200.0 AZN Rashad: 2500.0 AZN Rashad earns 2500.0
- В классе
Managerнет методовgetName()иdescribe(), но они работают — они унаследованы от родителя. - Метод
salary()переопределён (override): то же имя и параметры, но новое поведение. - Обрати внимание:
describe()написан в родителе, но для менеджера показал 2500. Когда он вызываетsalary(), работает версия фактического класса объекта. protected-поля видны наследникам, но не внешнему коду (из других пакетов).
Полиморфизм
Полиморфизм («многоформенность») означает, что переменная родительского типа может ссылаться на объект любого подкласса, а при вызове метода работает версия фактического класса объекта. Ниже в массиве Shape лежат круги и прямоугольники, и цикл вызывает area(), не разбираясь, где что, — каждая фигура считает свою площадь по-своему.
public class Main {
static double round2(double x) {
return Math.round(x * 100) / 100.0;
}
public static void main(String[] args) {
Shape[] shapes = { new Circle(1), new Rectangle(3, 4), new Circle(2) };
double total = 0;
for (Shape s : shapes) {
System.out.println(s.name() + ": " + round2(s.area()));
total += s.area();
}
System.out.println("Total: " + round2(total));
}
}
class Shape {
String name() { return "Shape"; }
double area() { return 0; }
}
class Circle extends Shape {
private double r;
Circle(double r) { this.r = r; }
@Override String name() { return "Circle"; }
@Override double area() { return Math.PI * r * r; }
}
class Rectangle extends Shape {
private double w, h;
Rectangle(double w, double h) { this.w = w; this.h = h; }
@Override String name() { return "Rectangle"; }
@Override double area() { return w * h; }
}Circle: 3.14 Rectangle: 12.0 Circle: 12.57 Total: 27.71
Circle — π · r². Выбери и другие фигуры: для каждой из них можно было бы написать свой подкласс.Сила полиморфизма в том, что если завтра добавить класс Triangle, цикл в main менять не придётся. Код зависит от общего типа (Shape), а не от конкретных классов. Именно так растут большие программы.
Проверка типа с instanceof
Иногда нужно узнать конкретный тип объекта. Выражение o instanceof String s проверяет, является ли o строкой, и если да, сразу помещает его в переменную s типа String. Такая запись (pattern matching) доступна начиная с Java 16.
public class Main {
public static void main(String[] args) {
Object[] things = { "Baku", 42, new Dog("Rex"), 3.5 };
for (Object o : things) {
if (o instanceof String s) {
System.out.println("String of length " + s.length());
} else if (o instanceof Dog d) {
d.bark();
} else {
System.out.println("Something else: " + o);
}
}
}
}
class Dog {
private String name;
Dog(String name) { this.name = name; }
void bark() { System.out.println(name + " says Woof!"); }
}String of length 4 Something else: 42 Rex says Woof! Something else: 3.5
Главное
class B extends A—Bнаследует поля и методыA; в Java класс может наследоваться только от одного класса.super(...)вызывает конструктор родителя, аsuper.method()— метод родителя.@Overrideзаставляет компилятор проверить, что метод действительно заменяет метод родителя.- Полиморфизм: переменная родительского типа ссылается на объект подкласса, а срабатывает метод фактического класса объекта.
o instanceof Type tпроверяет тип и сразу кладёт объект в новую переменную.
Проверь себя
Вопросов: 10. Каждый правильный ответ приносит XP.