Ответ
Да, наследование может нарушить иммутабельность класса, если не предприняты специальные меры.
Иммутабельный (неизменяемый) класс должен гарантировать, что его состояние не может быть изменено после создания. Наследование создает риски:
- Подкласс может добавить изменяемые поля.
- Подкласс может переопределить методы, которые в родительском классе казались "безопасными", и изменить внутреннее состояние.
Пример нарушения иммутабельности через наследование:
// Предположительно иммутабельный родительский класс
public class ImmutablePoint {
private final int x;
private final int y;
public ImmutablePoint(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() { return x; }
public int getY() { return y; }
}
// Подкласс, который делает объект изменяемым
public class MutablePoint extends ImmutablePoint {
private int z; // Добавлено изменяемое поле!
public MutablePoint(int x, int y) {
super(x, y);
}
public void setZ(int z) { this.z = z; } // Метод-мутатор
}
// Теперь объект, воспринимаемый как ImmutablePoint, может изменяться.
Способы защиты иммутабельности:
- Объявите класс как
final. Это предотвращает создание подклассов.public final class ImmutablePoint { ... } - Сделайте все конструкторы
privateилиpackage-privateи используйте фабричные методы. Это контролирует создание экземпляров. - Отдавайте предпочтение композиции перед наследованием. Включайте функциональность, делегируя вызовы внутреннему объекту, а не расширяя класс.
Вывод: Без защиты (например, ключевого слова final) иммутабельность класса не гарантирована в контексте наследования.