Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Переопределение (Override) в Java
Переопределение (Override) — это механизм полиморфизма в Java, который позволяет подклассу предоставить собственную реализацию метода, определенного в суперклассе. Это одна из ключевых концепций объектно-ориентированного программирования.
Определение и назначение
Переопределение — это когда подкласс создает новую версию метода, унаследованного от суперкласса, с той же сигнатурой (имя, параметры, возвращаемый тип).
// Суперкласс
public class Animal {
public void makeSound() {
System.out.println("Издает звук");
}
}
// Подкласс переопределяет метод
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Собака лает: Гав!");
}
}
// Подкласс переопределяет метод
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Кошка мяукает: Мяу!");
}
}
Полиморфизм в действии
public void animalSounds() {
Animal animal1 = new Dog(); // Полиморфная переменная
Animal animal2 = new Cat();
animal1.makeSound(); // Выведет: Собака лает: Гав!
animal2.makeSound(); // Выведет: Кошка мяукает: Мяу!
// Динамическое связывание (Dynamic Binding)
// Вызванный метод определяется в runtime, а не compile time
}
Правила переопределения
1. Сигнатура метода должна совпадать ТОЧНО
public class Parent {
public void method(int x) {}
}
public class Child extends Parent {
// ПРАВИЛЬНО - переопределение
@Override
public void method(int x) {
System.out.println("Child method");
}
// НЕПРАВИЛЬНО - перегрузка (overloading), не переопределение
public void method(String s) {}
// НЕПРАВИЛЬНО - другой возвращаемый тип
// public int method(int x) {} // Ошибка компиляции
}
2. Модификатор доступа не может быть более ограничивающим
public class Parent {
public void publicMethod() {}
protected void protectedMethod() {}
private void privateMethod() {} // НЕ может быть переопределен
}
public class Child extends Parent {
// ПРАВИЛЬНО - public может остаться public
@Override
public void publicMethod() {}
// ПРАВИЛЬНО - protected → public (расширение доступа)
@Override
public void protectedMethod() {}
// НЕПРАВИЛЬНО
// @Override
// protected void publicMethod() {} // Ошибка! Сужение доступа
}
3. Возвращаемый тип может быть подтипом (Covariant Return Types)
class Parent {
public Number getValue() {
return 10;
}
}
class Child extends Parent {
// ПРАВИЛЬНО - Integer является подтипом Number
@Override
public Integer getValue() {
return 20;
}
}
4. Аннотация @Override
public class Child extends Parent {
// Аннотация помогает избежать ошибок при переопределении
@Override
public void myMethod() {
// Если вы опечатались в имени метода,
// компилятор выведет ошибку
}
}
Отличие от Overloading (перегрузки)
public class Calculator {
// Перегрузка (Overloading)
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
public int add(int a, int b, int c) {
return a + b + c;
}
}
public class Parent {
public void print(int x) {
System.out.println("Parent: " + x);
}
}
public class Child extends Parent {
// Переопределение (Override) - ТА ЖЕ сигнатура
@Override
public void print(int x) {
System.out.println("Child: " + x);
}
// Перегрузка (Overloading) - ДРУГАЯ сигнатура
public void print(String s) {
System.out.println("Child String: " + s);
}
}
Практические примеры
Пример 1: Интерфейсы и реализация
public interface Shape {
double getArea();
String getDescription();
}
public class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
@Override
public String getDescription() {
return "Круг с радиусом " + radius;
}
}
public class Rectangle implements Shape {
private double width, height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double getArea() {
return width * height;
}
@Override
public String getDescription() {
return "Прямоугольник " + width + "x" + height;
}
}
Пример 2: Иерархия классов
public abstract class Vehicle {
public abstract void start();
public abstract void stop();
}
public class Car extends Vehicle {
@Override
public void start() {
System.out.println("Машина заводится двигателем");
}
@Override
public void stop() {
System.out.println("Машина останавливается");
}
}
public class Bicycle extends Vehicle {
@Override
public void start() {
System.out.println("Велосипед готов к поездке");
}
@Override
public void stop() {
System.out.println("Велосипед останавливается");
}
}
Динамическое связывание (Runtime Polymorphism)
public void driveVehicle(Vehicle vehicle) {
vehicle.start(); // Вызов переопределенного метода
// Какой именно start() будет вызван, определяется в runtime
vehicle.stop();
}
public void test() {
Vehicle car = new Car();
Vehicle bike = new Bicycle();
driveVehicle(car); // Выведет "Машина заводится..."
driveVehicle(bike); // Выведет "Велосипед готов..."
}
Ошибки при переопределении
public class Parent {
public int getValue() {
return 10;
}
}
public class Child extends Parent {
// ОШИБКА 1: Другой возвращаемый тип
// public void getValue() {} // Ошибка компиляции
// ОШИБКА 2: Другая сигнатура параметров
// public int getValue(int x) {} // Это перегрузка, не переопределение
// ОШИБКА 3: Сужение модификатора доступа
// private int getValue() {} // Ошибка компиляции
// ПРАВИЛЬНО
@Override
public int getValue() {
return 20;
}
}
Когда использовать переопределение
- Полиморфизм - разные классы имеют разные реализации одного метода
- Абстрактные методы - подклассы должны реализовать интерфейс/абстрактный класс
- Специализация - подкласс уточняет или расширяет поведение суперкласса
- Замена поведения - полностью переопределить логику метода
Ключевые моменты
- Переопределение включает динамическое связывание
- Метод выбирается в runtime, основываясь на типе объекта
- Должна совпадать сигнатура метода (имя и параметры)
- Возвращаемый тип может быть подтипом (covariant)
- Модификатор доступа не может быть более ограничивающим
- Используйте @Override для проверки корректности