可变类作为不可变类的子类

dea*_*mon 12 java oop inheritance mutable immutability

我希望有这样的不可变Java对象(强烈简化):

class Immutable {

    protected String name;

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

    public String getName() {
        return name;
    }

}
Run Code Online (Sandbox Code Playgroud)

在某些情况下,对象不仅应该是可读的而且是可变的,因此我可以通过继承添加可变性:

public class Mutable extends Immutable {

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

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

}
Run Code Online (Sandbox Code Playgroud)

虽然这在技术上很好,我想知道它是否符合OOP和继承,mutable也是类型不可变的.我想避免OOP犯罪抛出UnsupportedOperationException不可变对象,就像Java集合API那样.

你怎么看?还有其他想法吗?

Jon*_*eet 14

避免调用父"不可改变的",因为它成为了子类谎言-如果你希望使类不可变的,它应该是最后的太为了防止正是这个问题.

Joda Time使用"ReadableXXX"来表示"此类仅提供读访问权限;其他子类可能是可变的".我不确定我是否喜欢这个想法,但我不能说我见过很多选择.

基本上问题在于表达否定 - Immutable描述你不能做什么(改变它)并且在子类中不能明智地强制执行.(即使其中的字段Immutable是最终的,也不会阻止具有自己的可变字段的子类.)


les*_*es2 5

您的子类很糟糕,因为它违反了Liskov 替换原则。不要这样做。

  • 不,它没有。`Immutable` 的实例可以替换为 `Mutable` 的实例,而不会改变代码的行为。 (2认同)

sup*_*cat 5

我建议你应该有一个可继承的基本“ReadableFoo”类、一个派生的密封 ImmutableFoo 类和其他派生的 MutableFoo 类。不关心 Foo 是否可变的代码可以接受 ReadableFoo。需要保证不会更改的 Foo 的代码可以接受 ImmutableFoo。需要更改 Foo 的代码可以接受 MutableFoo。

请注意,ImmutableFoo 和 MutableFoo 的构造函数通常应接受 ReadableFoo。这样,任何 Foo 都可以转换为可变或不可变版本。