2011-06-09 64 views
5

我有點不清楚要在將類中的所有成員私人化並採取公共方法處理突變方面採取多大的想法。原始類型不是問題,它是我不清楚的封裝對象。使對象成員變爲私有的好處是能夠隱藏不適用於正在構建的類的上下文的方法。缺點是你必須提供公共方法來傳遞參數給底層對象(更多的方法,更多的工作)。在其他方面,如果你想讓所有的方法和屬性暴露給底層對象,你能不能公開對象? 以這種方式暴露對象有什麼危險?環保對象應該公開還是私密?

例如,我會發現將矢量或數組列表中的所有內容都暴露出來會很有用。我能想到的唯一缺點是,公共成員可能會通過隱式轉換(或其他影響)來分配類型。是否能夠減少潛在的問題?

只是一個側面說明:我明白,真正的詮釋意味着成員是私人的。

+0

見迪米特法則http://en.wikipedia.org/wiki/Law_of_Demeter,在OOP語言中,您應該儘量減少依賴關係。 這取決於「類」是否真正具有功能,或者實際上是數據結構。如果它只是一個數據結構,那麼getters'n'setter看起來有點過分,特別是如果所有的字段都是不可變的(final)。 – earcam 2011-07-02 19:05:20

回答

2

以這種方式暴露對象有什麼危險?

更改這些對象的類型需要將接口更改爲類。使用私有對象+公共getter/setter,只需要修改getter和setter中的代碼,假設你想保持返回的東西一樣。

請注意,這就是爲什麼屬性在諸如Python之類的語言中很有用,因爲它在技術上沒有私有類成員,最多隻能隱藏類成員。

+1

但你不覺得這是宣佈'私人對象+ public getters/setters'的結果嗎?如果他宣佈一切公開?雖然由於其他許多原因,我不建議這樣做,但我不認爲這個答案證明 – 2011-07-02 05:27:03

+0

這個問題是正確的,「如果他宣佈一切公開,該怎麼辦?」然後沒有封裝,並且改變直接暴露的類的成員將需要改變訪問直接暴露的成員並期望它以某種方式行爲的任何東西。你正在考慮這個問題。 – JAB 2011-07-05 13:39:24

0

面向對象的設計只是一個指導原則。從使用你班級的人的角度思考它。平衡OOD,使其直觀易用。

+0

好吧。那麼你會希望你的命名約定與該類的設計保持一致。所以,如果你有一個公開的整數向量來保存素數,我想這可能是一個糟糕的形式,給一個像「PrimeVector」 – 2011-06-09 20:02:44

+0

這樣的名字顯然你想稱之爲「VectorPrime」。 – JAB 2011-06-09 20:08:35

+1

這麼多基於你手頭任務的細節。例如,如果我們正在談論Java,其中Vector是一個衆所周知的類,並且您正在設計Java程序所使用的類,那麼我的首選是將它命名爲「PrimeNumbers」以及類型向量。如果您使用的語言不同,您將自己的類命名爲Vector,則還需要在界面中公開該類。如果你正在做一個非強類型的接口,我會稱之爲「PrimeNumbersVector」。另外,如果您正在編寫COM接口,還有其他注意事項。 – 2011-06-09 20:18:33

1

使實例變量公開的問題是,你以後永遠不會改變主意,並且使它們變爲私有的,而不會破壞依賴於直接公共訪問這些實例變量的現有代碼。一些例子:

  • 您決定以後讓你的類線程安全的增值經銷商,或可能通過使用一個ThreadLocal創建每個線程的值的新副本同步所有訪問實例。如果任何線程可以直接訪問變量,就不能這樣做。

  • 使用你的向量或數組列表的例子 - 在某些時候,你意識到在你的代碼中存在一個安全缺陷,因爲這些類是可變的,所以其他人可以替換列表的內容。如果這隻能通過訪問方法獲得,你可以根據請求通過創建一個不可變的副本來輕鬆解決問題,但不能用公共變量來實現。

  • 稍後您會意識到,您的一個實例變量是多餘的,可以基於其他變量派生。如果您使用訪問器,再次輕鬆,使用公共變量不可能。

我認爲它歸結爲一個實用的點 - 如果你知道你是誰將會使用這個代碼只有一個,而它的痛苦,你寫的訪問器(每個IDE會爲你做它自動),並且如果您決定中斷API,則不介意稍後更改自己的代碼,然後繼續。但是如果其他人將會使用你的班級,或者如果你希望稍後爲了自己的使用而重構,可以使用訪問器。

0

您可能遇到的問題取決於您使用的語言以及它如何處理返回語句或賦值運算符。在某些情況下,它可能會給你一個參考,或在其他情況下的值。例如,假設你有一個計算素數的PrimeCalculator類,那麼你有另一個類來處理這些素數。

public PrimeCalculator calculatorObject = new PrimeCalculator(); 

Vector<int> primeNumbers = calculatorObject.PrimeNumbersVector; 
/* do something complicated here */ 
primeNumbers.clear(); // free up some memory 

當你以後使用這個東西,可能在另一個類,你不想再計算數字的開銷,所以你使用相同的calculatorObject。

Vector<int> primes = calculatorObject.PrimeNumbersVector; 
int tenthPrime = primes.elementAt(9); 

在這一點上可能並不完全清楚primes和primeNumbers是否引用相同的Vector。如果他們這樣做,試圖從素數中獲得第十個素數將會導致錯誤。

如果您仔細瞭解並瞭解您的情況到底發生了什麼,但是您使用函數返回值而不是直接分配變量的誤差範圍更小,您可以這樣做。

0

那麼你可以檢查後:

first this

then this

這應該可以解決你的困惑。 它解決了我的!感謝Nicol Bolas

而且閱讀接受的答案(也注意到由我(在倒數第二個評論中給出的鏈接中的第一篇文章))

下面的評論中也可以訪問the wikipedia post

相關問題