2010-05-26 54 views
31

我有一個對象,它將一些數據存儲在列表中。實現可能會稍後改變,我不想將內部實現公開給最終用戶。但是,用戶必須有能力修改和訪問這個數據集合。目前我有這樣的事情:使用列表或集合更好嗎?

public List<SomeDataType> getData() { 
    return this.data; 
} 

public void setData(List<SomeDataType> data) { 
    this.data = data; 
} 

這是否意味着我已允許內部實現細節泄漏?我應該這樣做嗎?

public Collection<SomeDataType> getData() { 
    return this.data; 
} 

public void setData(Collection<SomeDataType> data) { 
    this.data = new ArrayList<SomeDataType>(data); 
} 
+9

有一點需要記住的是,如果你像這樣返回實際的集合或列表,你允許別人做他們想做的任何事情,包括刪除項目甚至清除整個事情。您最好返回一個不可變的包裝或列表副本。 – 2010-05-26 23:55:57

+1

@PaulTomblin是真實的,但它對系統有點矯枉過正和人爲的開銷。不可修改的包裝器在處理由持久性中間件管理的對象時是有意義的,甚至在極少數情況下也是如此。 – comeGetSome 2013-05-10 22:06:03

+0

@comeGetSome,這就是爲什麼我說「可能」而不是「必須」。這取決於用例 - 如果我爲他人使用API​​,我會返回一個副本或包裝。如果是爲了我自己或是爲了值得信任的同事,我會在javadoc中放入一個大的「不要修改這個價值」,然後放在那裏。 – 2013-05-11 15:21:44

回答

24

它只是取決於,你想讓你的用戶能夠索引到數據?如果是,請使用列表。兩者都是接口,所以你不會泄漏實現細節,實際上,你只需要決定所需的最小功能。

0

如果我擔心模糊內部表示我的數據給外部用戶,我會使用XML或JSON。無論哪種方式,它們都相當普遍。

+0

是否意味着字符串返回類型總是? – erdogany 2010-05-27 08:59:12

+0

當然。 XML和JSON意圖是非常普遍的,什麼可能比字符串更普遍? – Cyberherbalist 2010-05-27 20:19:46

+2

那麼,如果我在應用程序之間傳遞數據,我將使用這種編碼。但是,如果我正在談論函數的返回值...將其轉換爲XML,將其作爲String返回,然後調用者必須解析XML?這僅僅是爲了返回一個數組而非常複雜和繁瑣。 – Jay 2010-05-28 14:44:06

1

是的,如果您的第一個替代方法不是您的接口合約的一部分,並且該方法總是返回List,那麼它會泄漏實現細節。此外,允許用戶代碼替換您的集合實例有點危險,因爲它們傳遞的實現可能不像您期望的那樣運行。

當然,這完全取決於您對用戶的信任程度。如果你把Python哲學稱作「我們都在這裏同意大人」,那麼第一種方法就好了。如果你認爲你的圖書館會被沒有經驗的開發者使用,你需要盡一切可能「照顧」他們,並確保他們不會做錯什麼,那麼最好不要讓他們設置收集,甚至不要讓他們返回實際收集。而是返回一個(淺)副本。

+1

java.util.Collections包含像unmodifiableList()這樣的靜態方法,它只是簡單地包裝集合,以便所有修改集合的方法都會返回錯誤。由於實例化包裝器是一個常量操作,因此即使是淺拷貝也是可取的(如果客戶端代碼需要可變集合,它可以自己生成)。 – 2010-06-05 18:14:28

0

這取決於您希望提供給用戶的保證。如果數據是連續的,以便元素的順序很重要,並且允許重複,則使用列表。如果元素的順序無關緊要,可能會或可能不允許重複,請使用集合。既然你實際上返回了底層集合,你不應該同時擁有一個get和set函數,只有一個get函數,因爲返回的集合可能會發生變異。此外,提供設置功能允許用戶更改集合類型,而您可能希望特定類型由您控制。

5

使用最通用的類​​型,即集合,除非有一些明確的理由使用更具體的類型 - 列表,否則最有意義。但是無論你做什麼,如果這是公共消費的API,請在文檔中明確它的作用;如果它返回集合的淺表副本如此說。

7

當返回一個接口或類在高層次結構中的實現時,經驗法則是聲明的返回類型應該是最高級別,它提供了準備保證給調用者的最小功能,而且呼叫者合理需要。例如,假設你真正返回的是一個ArrayList。 ArrayList實現List和Collection(除其他外)。如果你期望調用者需要使用get(int x)函數,那麼它不會返回一個Collection,你需要返回一個List或者ArrayList。只要你沒有看到任何理由,爲什麼你會改變你的實現來使用列表以外的其他東西 - 比如一個Set - 那麼正確的答案是返回一個List。我不確定ArrayList中是否存在不在List中的任何函數,但如果存在,則會應用相同的推理。另一方面,一旦你返回一個List而不是一個Collection,你現在已經在某種程度上鎖定了你的實現。您放入API越少,您對未來改進的限制就越少。

(在實踐中,我幾乎總是返回在這種情況下一個列表,它從來沒有燒掉了我,但我可能真的應該返回一個Collection)

9

的能力索引通過列表名單獨立.get(int),那麼用戶(或您)是否期望集合中的元素處於可靠和可預測的順序?收藏品可以有多個相同的物品?這些都是對更普通的集合不常見的列表的期望。這些是我在確定要向最終用戶公開哪個抽象時使用的測試。

14

返回列表符合最高適用界面的編程。

返回集合會導致用戶模糊不清,因爲返回的集合可能是:Set,List或Queue。

相關問題