[英]Returning an immutable reference to a mutable object in Java
基本上,我在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
是一個大對象,所以我不想進行成員復制,而只是通過引用傳遞它。 上面的代碼成功地允許任何Figure
存取SizeInfo
對象的數據,但也允許Figure
修改該對象。 由此類行為引起的錯誤可能很難跟蹤,因此我想向SizeInfo
傳遞“不可變的引用”。
到目前為止,我發現的最佳解決方案是創建SizeInfo
的非靜態內部類, SizeInfo
僅包含getter:
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.export()
傳遞給該方法而不是sizeInfo
即可使其按預期工作。 從客戶端使用這非常容易,但是由於必須重復每個getter兩次而導致的代碼冗余絕對不是很好。 僅將吸氣劑放置在SizeInfo.Export
並將每個sizeInfo.getBaz()
替換為sizeInfo.export().getBaz()
方法更加糟糕。 這就是為什么我正在尋找一種更優雅的方法。
我意識到,就SizeInfo
而言,它太大而不能創建一個逐級克隆,因此可能無法相信這個特定示例。 但是,還有無數其他示例。 例如,如果我有一個可變的對象表示圖像的ARGB數據(可能是由於使用某些數學公式逐個像素生成了圖像),然后想要將其傳遞給一種方法,該方法應該對其進行修改,問題仍然會出現。
創建一個包含吸氣劑的ReadOnlySizeInfo
接口,使SizeInfo實現該接口,然后將該接口而不是SizeInfo傳遞給onSizeChanged()
。
您仍然會傳遞一個可變的對象,但是Figure對此並不了解:它所接收到的所有信息僅是ReadOnlySizeInfo
。 它仍然可以對對象進行強制轉換和變異,但這不再是一個錯誤:這將是一種邪惡的行為。
您可以創建一個接口,例如SizeInfoView
,其中僅包含吸氣劑。 然后, SizeInfo
將實現該接口,但還要添加setter。 Figure
將僅收到對SizeInfoView
接口的引用。 調用者當然仍然可以向下轉換為SizeInfo
,但是在C ++中,使用const_cast
會遇到相同的問題。 通常足以防止發生意外。
但是請記住,您得到的是不可修改的對象,而不是不可變的對象。 不同之處在於其他人可以對其進行修改,並且這些更改將反映在不可修改的視圖中。 但是同樣,對於C ++ const
引用也是如此。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.