2011-09-21 35 views
1

假設你有一個類Dog,有隱藏存取器,澄清需要

public class Dog { 

    private String name; 
    private double age; 

    // some setters 
    // some getters 

此外,你有一個類DogHandler,才使得Dog d的實例,並把它傳遞給Owner

我猜想,我可以

...製作狗的副本,然後傳遞給Owner,但這是一個昂貴的操作,我寧願避免它。

...想出了一個接口,Dog工具,它只包含干將,投Dog到該接口並通過沿

結果......在構造函數初始化設定的變量,根本不容許這種變化對象的實例

是否有其他方法可以確保對象的接收器無法修改它?

如何獲取包含某些數據的簡單bean並將其設置爲只讀?

+0

哪種語言? – Cratylus

+0

查看關於不可變類的[this post](http://stackoverflow.com/questions/5124012/immutable-classes)。 – Maciej

+0

我發現創建一個客戶端處理的基礎接口,比如像'Dog',然後是一個具體實現'MutableDog',它具有setter工作正常 –

回答

2

這可以通過幾種方式來實現,我可以建議您將它們的2:

一)與干將接口是好主意

B)創建一個從狗派生類具有setter方法方法受阻,像這樣的:

class UnmodifiedDog extends Dog { 
    public UnmodifiedDog(double age, String name) { 
     super.setAge(age); 
     super.setName(name); 
    } 
    @Override 
    public void setAge(double age) { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public void setName(String name) { 
     throw new UnsupportedOperationException(); 
    } 
} 

在DogHandler:

Dog createDog() { 
    return new UnmodifiedDog(10, "Fido"); 
} 

,您可以PAS s此向業主:

owner.receiveDog(dogHandler.createDog()); 
+0

爲什麼不使用現有的'Dog'類作爲數據源而不是傳遞年齡和名稱參數UnmodifiedDof構造函數?這就像'Collections.unmodifyableList' –

+0

@Misha一樣,如果你需要設置很多字段,比如在列表或其他集合中,這很重要。在這種情況下,我只有2個字段,因此,如果我在構造函數中傳遞Dog或僅傳遞2個字段,則無關緊要。但對於更多的領域,是的,你的建議是更好的方法 – smas

0

你在問題中提到的方法是非常標準的步驟來使Dog不變。唯一的另一個提示是強制要求Dog不能通過聲明該類爲final來覆蓋。

+0

更改類最終將無法在這種情況下工作,你仍然可以改變裏面的狗:年齡和名稱。 – smas

+0

@smas,你是對的。我離題了,開始討論不可變的_classes_,而原來的問題是關於不可變的_objects_。 – avik

0

在這裏提到的解決方案中,您還可以利用可見性修改器。如果DogOwner位於不同的包中,則可以將增變器的可見性設置爲默認(包)範圍或受保護範圍。

這將允許你保持DogDogHandler在同一封裝(並因此允許他們兩個相應變異的Dog對象),同時保持Owner對象分離(並因此防止它們作出任何修改Dog對象) 。

0

以下是使用接口和包訪問設置器的示例。


package blah.animal; 
public interface Dog 
{ 
    double getAge(); 
    String getName(); 
} 

package blah.animal; 
public class DogImpl implements Dog 
{ 
    private double age; // double seems wrong for age. 
    private String name; 

    ... getters (defined by Dog interface) 

    // package access setters. 
    void setAge(double newValue) 
    { 
    age = newValue; 
    } 

    void setName(String newValue) 
    { 
    name = newValue; 
    } 

    package blah.animal; 
    public class DogHandler 
    { 
    public static Dog newDog(double age, String name) 
    { 
     Dog returnValue = new DogImpl(); 
     returnValue.setAge(age); 
     returnValue.setName(name); 

     return returnValue; 
    } 
    } 

    package.blah.somethingelse; 
    public class Blam 
    { 
    private Dog myDog; 

    public Blam() 
    { 
     myDog = DogHandler.newDog(1.4D, "Tippy"); 
    } 
    }