繁体   English   中英

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

[英]Mutable class as a child of an immutable class

我希望有这样的不可变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;
    }

}

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

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

避免调用父“不可改变的”,因为它成为了子类谎言-如果想使一类不可变的,它应该是最后的太为了防止正是这个问题。

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

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

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

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

不可变类应该是final以避免可变子类型。

允许不可变类的子类型来破坏不可变合同使得类首先成为不可变类是没有意义的。 在Java允许你这样做的意义上它可能是合法的(在语言中不强制实现不变性),但只要它可以被分类,这样的类就不是真正不可变的。

这就是String是最终的原因。

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

我觉得你的代码很好奇。

为了实现这样的不可变行为,我宁愿依赖一个Immutable接口,只提供getter方法,而对象包含两者。 这样,依赖于不可变对象的操作就会调用接口,而其他操作则会调用该对象。

而且,如果您真的不希望将不可变对象转换为可变对象,则可以使用代理和所有企业工具(方面等)。 但通常情况下,依靠其他开发者的善意是让他们对错误负责的一种甜蜜方式(比如将不可变的东西变成可变的)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM