Наследование
Тема дорожной карты · Java
Наследование в Java — это объектно-ориентированный механизм, с помощью которого подкласс приобретает поля и методы суперкласса через ключевое слово extends, способствуя повторному использованию кода и обеспечивая полиморфную подстановку во всей системе типов Java. Java поддерживает только единственное наследование классов — класс может расширять ровно один суперкласс, — однако класс может реализовывать несколько Java Interfaces, что обеспечивает большую часть гибкости множественного наследования без проблемы ромба. Ключевое слово super позволяет подклассу явно вызывать конструктор суперкласса (super(args)) или метод суперкласса (super.methodName()), когда подкласс его переопределяет, что существенно для кооперативной инициализации в иерархиях наследования, используемых маппингами JPA @Entity и абстрактными базовыми классами Spring. Переопределение методов — это аналог наследования во время выполнения: когда подкласс объявляет метод с той же сигнатурой, что и метод суперкласса, JVM диспетчеризует вызовы к наиболее производному типу во время выполнения через виртуальную диспетчеризацию — аннотация @Override принудительно применяет это на этапе компиляции и защищает от опечаток. Наследование в Java напрямую взаимодействует с Java Garbage Collection (время жизни объектов не зависит от глубины иерархии) и системой ClassLoader (каждый класс в иерархии загружается независимо), являясь основой для понимания полиморфизма, абстрактных классов и паттернов проектирования вроде Template Method, используемых в Spring и Hibernate.
Как это работает
Наследование в Java строится на классах, наследовании (extends), интерфейсах (implements), полиморфизме (override + динамическая диспетчеризация), инкапсуляции (private-поля + public-методы), композиции (предпочтительнее наследования). Современная Java добавляет records (immutable носители данных), sealed классы/интерфейсы (закрытые иерархии для pattern matching), default-методы интерфейсов (эволюция без слома implementers).
Когда применять
Композиция (класс has-a) лучше наследования (класс is-a) по умолчанию — Liskov substitution исключает многие "is-a", выглядящие интуитивно. Records — для immutable data-классов. Sealed-типы — когда иерархия конечна (Shape — это Circle, Square или Triangle). Избегайте глубоких иерархий (>2-3 уровней = сигнал плохого дизайна).
Типичные ошибки
Ловушки Наследование: глубокие иерархии наследования, в которых "find usages" IDE не разберётся; mutable-поля без thread-safety на shared-объектах; override equals без hashCode (сломано в любом HashMap); toString сущности случайно выставляет колонку БД (утечка в логи); абстрактные базовые классы, смешивающие concern (разделяйте).