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

Я хочу иметь неизменяемые объекты 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 для неизменяемого объекта, как это делает API коллекций Java.

Что ты думаешь? Есть другие идеи?

12 голосов | спросил deamon 22 MarpmMon, 22 Mar 2010 19:21:49 +03002010-03-22T19:21:49+03:0007 2010, 19:21:49

5 ответов


0

Старайтесь не называть родительский объект «неизменным», поскольку он становится ложью в дочернем классе - если вы делаете хотите сделать класс неизменным, он также должен быть окончательным, чтобы точно решить эту проблему.

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

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

ответил Jon Skeet 22 MarpmMon, 22 Mar 2010 19:26:10 +03002010-03-22T19:26:10+03:0007 2010, 19:26:10
0

Я бы посоветовал иметь наследуемый базовый класс "ReadableFoo", производный запечатанный класс ImmutableFoo и другие производные классы MutableFoo Код, который не заботится о том, является ли Foo изменяемым или нет, может принять ReadableFoo. Код, который хочет, чтобы Foo гарантированно не изменялся, может принять ImmutableFoo. Код, который может понадобиться для изменения Foo, может принимать MutableFoo.

Обратите внимание, что конструкторы для ImmutableFoo и MutableFoo должны обычно принимать ReadableFoo. Таким образом, любой Foo будет преобразован в изменчивую или неизменяемую версию.

ответил supercat 23 Jam1000000amSun, 23 Jan 2011 05:55:13 +030011 2011, 05:55:13
0

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

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

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

ответил Kris 22 MarpmMon, 22 Mar 2010 19:25:15 +03002010-03-22T19:25:15+03:0007 2010, 19:25:15
0

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

ответил les2 22 MarpmMon, 22 Mar 2010 19:39:06 +03002010-03-22T19:39:06+03:0007 2010, 19:39:06
0

Я нахожу ваш код довольно любопытным.

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

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

ответил Riduidel 22 MarpmMon, 22 Mar 2010 19:31:45 +03002010-03-22T19:31:45+03:0007 2010, 19:31:45

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132