基本的には、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のコピーを作成したくないとしましょう、しかしただ渡しますそれを参照してください。上記のコードは、Figure
がSizeInfo
オブジェクトのデータにアクセスできるようにすることに成功しましたが、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データを表す可変オブジェクトがある場合(おそらく、イメージがある数式を使用してピクセルごとに生成されているため)、できないメソッドに渡したいと思ったそれを変更するには、問題は引き続き発生します。