Изменяемый класс как ребенок неизменного класса

Я хочу иметь неизменные объекты Java как это (сильно упрощенный):

class Immutable {

    protected String name;

    public Immutable(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

}

В некоторых случаях объект должен не только быть читаемым, но изменяемым, таким образом, я мог добавить переменчивость посредством наследования:

public class Mutable extends Immutable {

    public Mutable(String name) {
        super(name);
    }

    public void setName(String name) {
        super.name = name;
    }

}

В то время как это прекрасно технически, интересно, соответствует ли это ООП и наследованию, которое изменяемый также имеет неизменный тип. Я хочу избежать преступления ООП для броска UnsupportedOperationException для неизменного объекта как наборы Java API делает.

Что Вы думаете? Какие-либо другие идеи?

12
задан deamon 30 September 2011 в 18:51
поделиться

4 ответа

Избегайте называть родительский элемент "неизменяемым" потому что это становится ложью в дочернем классе - если вы действительно хотите сделать класс неизменяемым, он также должен быть окончательным, чтобы предотвратить именно эту проблему.

Joda Time использует «ReadableXXX», чтобы дать понять, что «этот класс предоставляет только доступ для чтения; другие подклассы могут быть изменяемыми». Я не уверен, нравится ли мне эта идея, но не могу сказать, что видел много альтернатив.

В основном проблема заключается в выражении отрицания - Неизменяемый описывает то, что вы не можете делать (изменять его), и что не может быть разумно реализовано в подклассах. (Даже если бы поля в Immutable были окончательными, это не остановило бы подкласс, имеющий свои собственные изменяемые поля.)

14
ответ дан 2 December 2019 в 06:08
поделиться

Мне ваш код довольно любопытен.

Чтобы реализовать такое поведение Immutable, я предпочел бы полагаться на интерфейс Immutable , предоставляющий только метод получения, в то время как объект содержит оба. Таким образом, операции, основанные на неизменяемых объектах, вызывали бы интерфейс, а другие вызывали бы объект.

И, если вы действительно не хотите, чтобы ваши неизменяемые объекты были преобразованы в изменяемые, вы можете использовать прокси и все корпоративные инструменты (аспекты и т. Д.). Но обычно полагаться на добрую волю других разработчиков - это приятный способ заставить их нести ответственность за свои ошибки (например, преобразование неизменяемого в изменяемое).

1
ответ дан 2 December 2019 в 06:08
поделиться

Ваш подкласс плохой, потому что он нарушает принцип подстановки Лискова . Не делай этого.

3
ответ дан 2 December 2019 в 06:08
поделиться

Неизменяемые классы должны быть final именно во избежание изменяемых подтипов.

Разрешение подтипу неизменяемого класса нарушать неизменяемый контракт делает бессмысленным изначально иметь неизменяемый класс. Это может быть законным в том смысле, что Java позволяет вам это делать (неизменяемость не обеспечивается в языке), но такой класс не действительно неизменяемый, если он может быть подклассом.

Вот почему String является окончательным.

3
ответ дан 2 December 2019 в 06:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: