2012-08-11 67 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]。如果一個正在使用的陣列的很大一部分是對角線陣列,那麼可以爲每個這樣的實例節省大量的內存。雖然讓課程變得可擴展性會讓人有可能以一種可能會突變的方式擴展它,但也會讓程序員知道某個程序所使用的許多數組適合某種特定形式的程序員設計一個類來優化存儲該表單。