2016-04-30 15 views
0

基本的には、Javaで可変オブジェクトがあり、その状態は特定のクラスのいくつかのメソッドによってアクセスされ、変更されます。オブジェクトに格納されたデータは別のクラスでも使用されますが、違いは2番目のクラスでデータを変更することを許可しないでください。Javaの可変オブジェクトへの不変参照の返却

C++では、普通はオブジェクトの参照をconstに渡すだけですが、Javaでは直接的な同等物は存在しません。

だけ明確にするために、次のコードスニペットは、私は心の中で持っているものを示しています。

public interface Figure 
{ 
    void onSizeChanged(SizeInfo info); 
    void draw(); 
} 
public class FigureView extends View 
{ 
    private Figure figure; 
    private SizeInfo sizeInfo; 

    ... 

    public void onResize() 
    { 
     //Modify the state of sizeInfo, then pass it to the figure. 
     figure.onSizeChanged(sizeInfo); 
    } 
} 

だがSizeInfoが大きなオブジェクトであるので、私はmemberwiseのコピーを作成したくないとしましょう、しかしただ渡しますそれを参照してください。上記のコードは、FigureSizeInfoオブジェクトのデータにアクセスできるようにすることに成功しましたが、Figureはオブジェクトを変更することもできます。このような動作によって引き起こされるエラーは追跡が難しいかもしれないので、私はSizeInfoに「不変の参照」を渡したいと思います。

私がこれまでに発見した最善の解決策が唯一のゲッターから構成さSizeInfoの非static内部クラスを作成することです。このコードで

public class SizeInfo 
{ 
    //These represent the large set of data inside the class. 
    private long foo; 
    private double bar; 
    private Export mExport = new Export(); 

    //Setters (only available if you have a direct reference to SizeInfo): 
    public void incrementFoo() 
    { 
     foo++; 
    } 
    public void setBar(double bar) 
    { 
     this.bar = bar; 
    } 

    //SizeInfo getters: 
    public long getFoo() 
    { 
     return foo; 
    } 
    public double getBar() 
    { 
     return bar; 
    } 
    public double getBaz() 
    { 
     return bar * foo; 
    } 

    //A non-static inner class: 
    public class Export 
    { 
     public long getFoo() { return foo; } 
     public double getBar() { return bar; } 
     public double getBaz() { return bar * foo; } 
    } 
    public Export export() { return mExport; } 
} 

を、あなただけのFigureにメソッドシグネチャを変更する必要がありますonSizeChanged(SizeInfo)からonSizeChanged(SizeInfo.Export)まで、そしてsizeInfoの代わりにsizeInfo.export()をメソッドに渡して、期待通りに動作させる必要があります。これはクライアント側からの使用は非常に簡単ですが、各ゲッターを2回繰り返さなければならないことによるコードの冗長性は間違いなくエレガントです。ゲッターをSizeInfo.Exportに置き換え、sizeInfo.getBaz()sizeInfo.export().getBaz()に置き換えるのはさらに悪いことです。だから私はよりエレガントなアプローチを探しています。

SizeInfoが大きすぎてメンバーワイズクローンを作成できないという点でこの特定の例は信じられないかもしれません。しかし、他にもたくさんの例があります。たとえば、イメージのARGBデータを表す可変オブジェクトがある場合(おそらく、イメージがある数式を使用してピクセルごとに生成されているため)、できないメソッドに渡したいと思ったそれを変更するには、問題は引き続き発生します。

答えて

0

getterのみを含むインターフェイス、たとえばSizeInfoViewを作成できます。その後、SizeInfoはそのインターフェースを実装しますが、セッターも追加します。 Figureは、SizeInfoViewインターフェイスへの参照のみを受信します。呼び出し元はもちろんSizeInfoにダウンキャストできますが、C++では同じ問題がconst_castで発生します。通常は事故を防ぐのに十分です。あなたは変更不可能オブジェクト、ない不変オブジェクトを取得しているものの

ベア心​​の中で、。違いは、他の誰かが変更できることであり、その変更は変更不可能なビューに反映されるということです。しかし、同じことがC++ constの参考文献にも当てはまります。

0

getterを含むReadOnlySizeInfoインターフェイスを作成し、SizeInfoでそのインターフェイスを実装し、SizeInfoではなくインターフェイスをonSizeChanged()に渡します。

あなたはまだ変更可能なオブジェクトを渡しますが、Figureはそれについてはわかりません:受け取ったものについて知っているのは、それがReadOnlySizeInfoだということです。オブジェクトをキャストして変異させることはできますが、それはもはやバグではありません。悪い行為になります。

関連する問題