面向?qū)ο笳Z言類的語法幾乎都有私有成員,為什么需要私有成員呢?最近在寫一個(gè)類的時(shí)候严沥,發(fā)現(xiàn)其他類在用到這個(gè)類的時(shí)候,基本都是要讀取它的屬性拷沸,一般我們會(huì)被教導(dǎo)說成員變量都設(shè)置為私有色查,通過getter和setter來獲取和修改它們,但是當(dāng)類的屬性比較多時(shí)撞芍,太多的存取器會(huì)讓這個(gè)類看起來非常龐大秧了,直接將類的屬性設(shè)置為公有,直接讀取它不就好了嗎序无,多省事验毡,為什么很多的書都會(huì)建議你將數(shù)據(jù)成員設(shè)置為私有呢?
首先帝嗡,當(dāng)類的屬性比較多時(shí)晶通,一般這個(gè)類設(shè)計(jì)得不好,可以進(jìn)一步拆分成更小的類哟玷。按照《代碼整潔之道》的說法狮辽,類和函數(shù)都要盡量短小,短小的類一般會(huì)更加內(nèi)聚巢寡,內(nèi)聚的類意味著成員變量在大多數(shù)成員函數(shù)中被使用到喉脖。可以將聯(lián)系緊密的成員變量抽離出來抑月,新建一個(gè)類來使用它們树叽。短小的類,其職責(zé)也更加明確爪幻,當(dāng)別人閱讀你的代碼的時(shí)候菱皆,通過閱讀類的名稱,基本上就能知道這個(gè)類的功能挨稿。
其次仇轻,如果類的屬性比較多,且經(jīng)常需要給其它類直接讀取修改奶甘,而且不好拆分篷店,怎么辦?這種類的對(duì)象更類似C語言中的結(jié)構(gòu)體臭家,或者JavaScript中的json疲陕,你只是想構(gòu)造一種結(jié)構(gòu)體來存儲(chǔ)一坨數(shù)據(jù),作為參數(shù)傳遞給其它函數(shù)或者類钉赁,并允許直接修改它們蹄殃。在C++語言中,可以將這種類聲明為struct類型你踩,并不要給他們?cè)O(shè)置成員函數(shù)诅岩,明確表示它們是一種結(jié)構(gòu)體讳苦。其它語言中可以嘗試使用Map之類數(shù)據(jù)結(jié)構(gòu)來代替,明確表達(dá)出它們是某種數(shù)據(jù)集合的含義吩谦。最喜歡TypeScript語言了鸳谜,TypeScript語言的interface關(guān)鍵字,可以直接聲明某種數(shù)據(jù)集合的類型式廷,非常方便咐扭。
除此之外,對(duì)于類的某些屬性滑废,我們沒有必要刻意把他們作為私有成員去處理蝗肪。有些類的屬性,可以預(yù)見在未來很長(zhǎng)一段時(shí)間都是穩(wěn)定的策严。比如說Image類穗慕,用來表示一張圖片,圖片有寬高屬性妻导,用cols和rows來表示。在使用Image類來表示一張圖像的時(shí)候怀各,我們沒有必要通過getRows或者getCols接口來訪問它們倔韭,rows和cols就是這個(gè)圖像非常基本的一個(gè)屬性瓢对。當(dāng)然它們最好是只讀類型的寿酌,不能直接修改,但是可以訪問硕蛹,一張?zhí)囟▓D片的寬高屬性是不變的醇疼。直接通過rows和cols訪問,語意也更加明確法焰。
class Image {
public:
Image(int r,int c):rows(r),cols(c){}
const int rows;
const int cols;
}
但是如果你的老板說秧荆,我要知道rows,cols屬性被調(diào)用了多少次,你就得加一個(gè)count屬性埃仪,在每個(gè)讀取rows的地方對(duì)count屬性自增1乙濒,就非常讓人難受。如果通過類的getRows函數(shù)來獲取rows卵蛉,就可以在函數(shù)中對(duì)count+1颁股,如下所示:
class Image {
private:
int rows;
int cols;
int countRows{0};
int countCols{0};
public:
Image(int r,int c):rows(r),cols(c){}
int getRows(){ countRows++; return rows; }
int getCols(){ countCols++; return cols; }
int getCounts() { return countRows + countCols; }
}
這樣子,我們就沒有必要在每個(gè)地方都countRows++傻丝,countCols++甘有,因?yàn)槟愕男枨笞兞耍xrows和cols就不能直接讀葡缰,要進(jìn)行一定的處理亏掀,這就是給私有變量設(shè)置存取器的好處忱反。同時(shí)在對(duì)私有成員進(jìn)行賦值時(shí),我們也可以對(duì)其進(jìn)行校驗(yàn)等工作幌氮。
但是缭受,我前面說了,rows和cols是非常穩(wěn)定的屬性该互,是一張?zhí)囟▓D片非趁渍撸基本的屬性,沒有哪個(gè)智障想知道rows和cols被調(diào)用了多少次吧宇智,或者對(duì)這兩個(gè)屬性有什么想法蔓搞,所以你直接將rows和cols設(shè)置為公有成員,沒什么不好随橘。
最后喂分,我覺得private被設(shè)計(jì)出來的初衷,就是為了封裝吧机蔗。暴露出來的接口應(yīng)該是穩(wěn)定的蒲祈,而類中的變量隨著需求的變動(dòng)有可能會(huì)增刪改,如果你沒有將這些變量設(shè)置為私有萝嘁,別人寫代碼的時(shí)候直接拿來用了梆掸,某天你把這個(gè)數(shù)據(jù)成員刪掉,人家的代碼就跑不動(dòng)了牙言,而你可能會(huì)覺得別人本來就不該直接用這個(gè)屬性酸钦。就像電腦一樣,使用電腦的人不需要知道什么是CPU咱枉、硬盤等卑硫,鼠標(biāo)鍵盤會(huì)用就好了。CPU什么的就像類的私有變量蚕断,你不想被別人亂動(dòng)欢伏,就把它封裝到機(jī)箱里,只暴露顯示器基括、鍵盤和鼠標(biāo)等給用戶調(diào)用颜懊。假如未來電腦不需要使用內(nèi)存條,也與你無關(guān)风皿,你依舊會(huì)使用電腦河爹。
說了這么多,最后還是這個(gè)結(jié)論桐款,平時(shí)養(yǎng)成好習(xí)慣咸这,在設(shè)計(jì)類時(shí)public變量越少越好!