可变和不可变的类

时间:2012-04-27 14:54:24

标签: java oop immutability mutable

我想在java中创建可变且不可变的节点,除了mutable之外,两者都应该是相同的。如何实现基类和可变和不可变类的两个派生类?

5 个答案:

答案 0 :(得分:4)

可变类和不可变类之间的区别在于,不可变类没有setter或任何其他修改内部状态的方法。状态只能在构造函数中设置。

调用父类Immutable是一个坏主意,因为当你有子类时,这将不再是真的。该名称会产生误导:

ImmutableNode node = new MutableNode();
((MutableNode)node).change();

答案 1 :(得分:4)

您需要做的就是创建一个带有受保护变量的基类

public class Base{
     protected int foo;
}

可变的人需要能够设置变量

public class MutableBase extends Base{
     public void setFoo(){}
}

不可知的只需要能够设置一次变量

public class ImmutableBase extends Base{
     public ImmutableBase(int foo){
          this.foo = foo;
     }
}

大多数不可变类都有方法对 中的变量进行操作,而 不会改变实例。 String这样做,你可能想要这样的东西

public ImmutableBase add(int bar){
     return new ImmutableBase(this.foo+bar);
}

关于这一点很酷的是,您可以为您的班级用户 控制/担心每个实例的内部。这使得它更容易使用,因为在Java中,所有内容都通过对象引用传递,因此如果您传递String或ImmutableBase,则不必担心它会被更改。

答案 2 :(得分:1)

不可变类是一个曾经创建过的类,它的内容无法更改。不可变对象是其状态无法更改的对象。

Java中不可变类的一个常见示例是String类。

答案 3 :(得分:1)

对于一个不可变的类,它必须被声明为final,并且它不能超过setter 方法。最终声明确保无法扩展它并添加其他可变属性。

class Base {
    protected int var1;
    protected int var2;

    public getVar1() {return var1;}
    public getVar2() {return var2;}
    }

    class Mutable extends Base {
      public setVar1(int var1) {this.var1 = var1}
      public setVar2(int var2) {this.var2 = var2}
    }

    final class Immutable extends Base { //final to avoid being extended and then implement the setters

    }

多数民众赞成我可以做的一点点?但为什么你需要这样的场景?

答案 4 :(得分:1)

另一种选择是使用与UnmodifiableList相同的策略。首先,创建一个指定类型的接口。

interface List<T>{
    List<T> add(T t);
    T getAt(int i);
    ...
}

然后使用所有业务逻辑实现可变类:

public class MutableList<T> implements List<T>{
    @Override
    List<T> add(T t){ ... }

    @Override
    T getAt(int i){ ... }

    ...
}

最后,创建您的不可变类以成为可变类的视图。您实现相同的接口,但将所有读取方法调用委托给查看的对象,并禁止任何带有异常的写访问。

public class UnmodifiableList<T> implements List<T>{
    //This guy will do all hard work
    private List delegate;

    public UnmodifiableList(List<? extends T> delegate){
        this.delegate = delegate;
    }

    //Forbidden mutable operation: throw exception!
    @Override
    List<T> add(T t){ 
        throw new UnsupportedOperationException("List is unmodifiable!");
    }

    //Allowed read operation: delegate
    @Override
    T getAt(int i){ 
        return delegate.getAt(i);
    }

    ...
}

这种方法的好处是,您只需要实现一次业务逻辑,并且可以先使用自己的方法和验证检查构建一个Object,然后再将其转换为可重定义的对象。