Что важно разработчику при написании кода с наследованием в Java
Что проверяют
Понимаете ли вы, что наследование это не способ переиспользовать код, а объявление контракта подстановки, и умеете ли выбирать между наследованием и композицией. Ответ уровня «наследование позволяет не дублировать код» интервьюер слышит постоянно и сразу спрашивает про минусы.
Как отвечать
Отправная точка: наследовать стоит, когда подкласс действительно частный случай базового и его можно подставить вместо базового, не ломая ожиданий вызывающего кода. Если нужно только переиспользование, берите композицию и делегирование: связь слабее, а поведение видно на месте.
Дальше практические правила:
- класс либо проектируется под наследование осознанно, либо закрывается через
final. Проектировать значит описать, какие методы вызываются изнутри других, и оставить понятные точки расширения; - не вызывать переопределяемые методы из конструктора: подкласс на этот момент ещё не инициализирован;
- переопределение помечать
@Override, не сужать видимость и не усиливать предусловия; - поля базового класса держать закрытыми,
protectedэто такой же публичный контракт, только для наследников; - помнить про
equalsиhashCode: подкласс с новым полем ломает симметрию сравнения.
class Base {
Base() { init(); }
void init() {}
}
class Child extends Base {
private final List<String> items = new ArrayList<>();
@Override void init() { items.size(); } // NPE: поле ещё не присвоено
}Где спотыкаются
Называют плюсом то, что правка базового класса сама расходится по всем наследникам. Ровно это и есть проблема хрупкого базового класса: безобидное изменение внутренней реализации ломает подклассы, которых автор не видел.
Второе: строят глубокие иерархии ради общего кода, и через пару уровней уже не сказать, откуда взялось поведение метода. Общий код спокойно живёт в отдельном классе, который вызывают.
Третье: переопределяют метод, меняя его смысл, и ломают подстановку. Классика: квадрат наследует прямоугольник, установка ширины меняет и высоту, и весь код, написанный под прямоугольник, начинает врать.