Наследование в Java
Наследование — это механизм, при котором один класс (подкласс, child) получает поля и методы другого класса (суперкласс, parent) и может добавлять к ним свои или переопределять унаследованные. Так строится иерархия типов: например, LedRgb — это разновидность Led, а Led — разновидность Device.
Главная цель наследования — переиспользование кода и моделирование отношения «является» (is-a). Если B наследник A, то любой объект B является объектом A, и ссылка типа A может указывать на объект B.
В Java множественное наследование классов запрещено: у класса есть только один прямой суперкласс. Если extends не указан, неявно наследуется java.lang.Object.
Синтаксис
class Parent {
// ...
}
class Child extends Parent {
// дополнительные поля/методы
}
Внутри подкласса доступно ключевое слово super — ссылка на «родительскую часть» объекта, обычно используется для вызова конструктора или переопределённого метода суперкласса.
Пример 1. Базовое наследование
class Device {
String name;
void info() {
System.out.println("Device: " + name);
}
}
public class Led extends Device {
int pin;
public static void main(String[] args) {
Led led = new Led();
led.name = "LED1";
led.pin = 13;
led.info(); // унаследовано
System.out.println("pin=" + led.pin);
}
}
Output:
Device: LED1
pin=13
Пример 2. Конструкторы и super(…)
class Device {
String name;
Device(String name) {
this.name = name;
System.out.println("Device(" + name + ")");
}
}
public class Sensor extends Device {
int pin;
Sensor(String name, int pin) {
super(name);
this.pin = pin;
System.out.println("Sensor(" + name + ", " + pin + ")");
}
public static void main(String[] args) {
new Sensor("DHT22", 4);
}
}
Output:
Device(DHT22)
Sensor(DHT22, 4)
Пример 3. Переопределение метода
class Device {
String name = "Generic";
void info() {
System.out.println("Это устройство: " + name);
}
}
public class Motor extends Device {
int speed = 0;
@Override
void info() {
System.out.println("Мотор " + name + ", скорость " + speed);
}
public static void main(String[] args) {
Device a = new Device();
Motor b = new Motor();
b.name = "Левый";
b.speed = 120;
a.info();
b.info();
}
}
Output:
Это устройство: Generic
Мотор Левый, скорость 120
Пример 4. Вызов родительской реализации через super
class Device {
String name = "X";
void info() {
System.out.println("[Device] " + name);
}
}
public class Sensor extends Device {
int pin = 7;
@Override
void info() {
super.info(); // выводит "[Device] X"
System.out.println("[Sensor] pin=" + pin);
}
public static void main(String[] args) {
new Sensor().info();
}
}
Output:
[Device] X
[Sensor] pin=7
Пример 5. Полиморфизм ссылок
class Device {
void hello() {
System.out.println("hello from Device");
}
}
class Led extends Device {
@Override
void hello() {
System.out.println("hello from Led");
}
}
public class Motor extends Device {
@Override
void hello() {
System.out.println("hello from Motor");
}
public static void main(String[] args) {
Device[] devs = { new Device(), new Led(), new Motor() };
for (Device d : devs) {
d.hello(); // вызовется метод фактического класса
}
}
}
Output:
hello from Device
hello from Led
hello from Motor
Пример 6. Иерархия из трёх уровней
class Device {
void on() { System.out.println("Device.on"); }
void off() { System.out.println("Device.off"); }
}
class Light extends Device {
void blink() { System.out.println("Light.blink"); }
}
public class Rgb extends Light {
void color(String c) { System.out.println("Rgb.color=" + c); }
public static void main(String[] args) {
Rgb rgb = new Rgb();
rgb.on(); // из Device
rgb.blink(); // из Light
rgb.color("red"); // из Rgb
}
}
Output:
Device.on
Light.blink
Rgb.color=red
Подводные камни
privateполя и методы суперкласса не доступны в подклассе напрямую — только через публичные/protected методы.super(...)(вызов конструктора родителя) должен быть первой строкой конструктора. Если его нет — Java неявно вставитsuper();(без параметров).Аннотация
@Override— не обязательна, но рекомендуется: компилятор сообщит, если вы случайно сделали не переопределение, а перегрузку.Поля не «переопределяются» — они скрываются. При обращении
a.fieldчерез ссылку типаAвы получите полеA, даже если объект на самом деле —B.Java не поддерживает множественного наследования классов. Если нужно «много родителей» — используют интерфейсы.
Класс с модификатором
finalнельзя наследовать; метод сfinalнельзя переопределить.
См. также
Примечание
Лицензия и источники
Концепция описана на основе официального Java Tutorial от Oracle (https://docs.oracle.com/javase/tutorial/), Oracle Free Documentation License. Перевод, примеры и пояснения — © AlashEd Wiki.