2012-08-11 63 views
0

我读的是有很多原因的SO线程作出级决赛,并在arcticle 其中两个是类:不变性VS不可扩展

1. To remove extensibility 
2. to make class immutable. 

的是否使一类不可变的更具特色以及它作为最终的(它的方法)?我没有看到两者之间的区别?

回答

2

Immutable object不允许改变他的状态。最终课程不允许继承自己。例如类Foo(见下文)是不可变的(的状态下,即_name从不改变)和Bar类是可变的(rename方法允许改变的状态):

final class Foo 
{ 
    private String _name; 

    public Foo(string name) 
    { 
    _name = name; 
    } 

    public String getName() 
    { 
    return _name; 
    } 
} 

final class Bar 
{ 
    private String _name; 

    public Bar(string name) 
    { 
    _name = name; 
    } 

    public String getName() 
    { 
    return _name; 
    } 

    public void rename(string newName) 
    { 
    _name = newName; 
    } 
} 
+0

我想这样做只是为了惩罚你的名字...... @ie。 I.E.这就像有一个这样的C++类: class foo {private:int a; public:b(int c)const {return a; }} – 2012-08-11 20:46:57

+0

对于不可变... – 2012-08-11 20:48:38

+0

@ChrisOkyen我已经添加了一个显示差异的示例 – 2012-08-11 20:54:26

0

它有时可识别类型的有用作为“可验证的不可变的”,这意味着静态分析可以证明:(1)一旦一个实例被构造,它的任何属性都不会改变,并且(2)它拥有一个引用的每个对象实例都是可验证的深不可变的。可扩展的类不能被证实是不可变的,因为静态分析器将无法知道是否可以创建可变子类,并且该可变子类的引用存储在应该是可验证的深不可变的对象中。

另一方面,有时抽象(因此可扩展)的类被指定为非常不可变的有用。抽象类无法强制派生类不可变,但任何可变派生类都应该被认为是“破碎”的。这种情况有点类似于要求两个报告自己“相等”的对象实例报告相同的哈希码。设计违反该要求的类是可能的,但是所导致的任何错误的散列表行为都是破碎的散列码函数的错误,而不是散列表。

例如,可能有一个抽象的ImmutableMatrix属性,它具有读取给定(行,列)位置处元素的方法。一种可能的实现方式是使用N * M个元素的数组来支持NxM ImmutableMatrix。另一方面,定义一些像ImmutableDiagonalMatrix这样的子类也可能是有用的,这些子类有N个元素的数组,其中Value(R,C)对于R == C将产生0,对于R == C将产生Arr[R]。如果一个正在使用的阵列的很大一部分是对角线阵列,那么可以为每个这样的实例节省大量的内存。虽然让课程变得可扩展性会让人有可能以一种可能会突变的方式扩展它,但也会让程序员知道某个程序所使用的许多数组适合某种特定形式的程序员设计一个类来优化存储该表单。