1. 程式人生 > >將成員變數宣告為private

將成員變數宣告為private

切記宣告資料成員為private。它為客戶提供了訪問資料的一致,細微劃分的訪問控制,允許約束條件獲得保證,而且為類的作者提供了實現上的彈性。

     protec並不比public更具有封裝性

不應該將資料成員宣告為public的三個理由

一、語法一致性

        如果資料成員不是public的,客戶訪問一個物件的唯一方法就是通過成員函式。如果在public介面中的每件東西都是函式,客戶就不必絞盡腦汁試圖記住當他們要訪問一個類的成員時是否需要使用圓括號,他們只要使用就可以了,因為每件東西都是一個函式。

二、精確控制成員變數的處理

       如果你讓一個數據成員為public,每一個人都可以讀寫訪問它,但是如果你使用函式去得到和設定它的值

,你就能實現禁止訪問,只讀訪問和讀寫訪問,甚至只寫訪問:

  1. class AccessLevels {
  2. public:
  3. ...
  4. int getReadOnly() const { return readOnly; }
  5. void setReadWrite(int value) { readWrite = value; }
  6. int getReadWrite() const { return readWrite; }
  7. void setWriteOnly(int value) { writeOnly = value; }
  8. private:
  9. int noAccess; // no access
  10. int readOnly; // read-only access
  11. int readWrite; // read-write access
  12. int writeOnly; // write-only access
  13. };
三、封裝:

如果你通過一個函式實現對資料成員的訪問,你可以以後改以某個計算來替換這個資料成員,使用你的類的人不會有任何察覺。

例如,假設你正在寫一個自動測速程式,當汽車通過,其速度便被計算並填入一個速度收集器內:

  1. class SpeedDataCollection {
  2. ...
  3. public:
  4. void addValue(int speed); // 新增一筆新資料
  5. double averageSoFar() const; // 返回平均速度
  6. ...
  7. };    

        現在考慮成員函式averageSoFar的實現:辦法之一是在類中用一個數據成員來實時變化迄今為止收集到的所有速度資料的平均值。無論何時averageSoFar被呼叫,它需返回那個資料成員的值。另一個方法是在每次呼叫averageSoFar時重新計算,通過分析集合中每一個數據值做成這些事情。

        誰能說哪一個最好?在記憶體非常緊張的機器(如,一臺嵌入式路邊偵測設裝置)上,或是一個很少需要平均值的應用程式中,每次都計算平均值可能是較好的解決方案;在一個頻繁需要平均值的應用程式中,速度比較重要,且記憶體不成問題,保持一個實時變化的平均值更為可取。重點在於通過一個成員函式訪問平均值(也就是說將它“封裝”),你能替換這兩個不同的實現(也包括其他你可能想到的)。

        封裝可能比它最初顯現出來的更加重要。如果你對你的客戶隱藏你的資料成員(也就是說,封裝它們),你就能確保類的約束條件總能被維持,因為只有成員函式能影響它們。此外,你預留了日後變更實現的權利如果你不隱藏你將很快發現,即使你擁有類的原始碼,你改變任何一個public的東西的能力也是非常有限的,因為有太多的客戶程式碼將被破壞。public意味著沒有封裝,沒有封裝意味著不可改變,尤其是被廣泛使用的類。被廣泛使用的類是最需要封裝的,因為它們可以從一種更好的實現中得益。



為什麼不應該宣告protected資料成員?

        反對protected資料成員的理由和public資料成員是類似的。關於語法一致性和細微劃分之訪問控制等理由顯然也適用於protected資料,就連封裝性上protected資料成員也不比public資料成員更好。

        某些東西的封裝性與“當其內容改變時可能造成的程式碼破壞量“成反比。所謂改變,也許是從類中移除它(就像上述的averageSoFar)。

        假設我們有一個public資料成員,隨後移除它,所有使用了它的客戶程式碼都被破壞,其數量通常大得難以置信,因此public資料成員是完全未封裝的。但是,假設我們有一個protected資料成員,隨後我們移除了它。現在有多少程式碼會被破壞呢?所有使用了它的派生類都被破壞,典型情況下,程式碼的數量還是大得難以置信,因此protected資料成員就像public資料成員一樣沒有封裝。在這兩種情況下,如果資料成員發生變化,被破壞的客戶程式碼的數量都大得難以置信。一旦你宣告一個數據成員為public或protected,而且客戶開始使用它,就很難再改變與這個資料成員有關的任何事情。有太多的程式碼不得不被重寫,重測試,重文件化,或重編譯。

       從封裝的觀點來看,實際只有兩個訪問層次:private(提供了封裝)與其他(沒有提供封裝)