跳到主要內容

將成員變數宣告為private

這是最近寫港股,大量運用繼承的感悟。最初的認知,是認為public是危險的,如果讓不相干或不應影響的類別修改他,可能會造成邏輯上的嚴重錯誤,但是就protected的而言應是相對安全的,既然是繼承才能使用,使用邏輯應該一致,不會發生邏輯錯誤的問題。所以我認為如果子類別需要用的變數,便直接宣告成protected就好了,避免回頭再修改;但若不可避免的,非繼承關係的類別需要用到更用變數,那麼就用只好宣告public。在effective c++看到此要點時,真的不認為有必要只能宣告為private?合理的注意存取層級不就好了。但此要點在書中所述最重要的原因卻非「安全」而是「封裝」,最近遇到的真實案例,讓我瞭解到封裝的可貴。

這個問題發生背景為港股的指數走勢圖要套用個股走勢圖的架構,從大架構來看,似乎只要將指數的相關的資料帶入就可以了,但問題在於個股的資料是用float的vector來紀錄資料,但是指數卻是double。把double轉為float,大轉小這可不是很好的作法,但是把底層改為double,又會發現不只底層的class要改,他的繼承class同樣接受了這樣的災難。

我簡化實際寫法,但情況差不多(紅色是改為double的情形),如下ex:
Class BaseChart //基層類別
{
protected:
vector<float> vfChartData; //因新需求,將其改為double
}

Class DerivedChart //繼承類別
{
void SetData{  //某個method
vector<float> vfDerivedData;
… //中間做了一些設定。
vfDerivedData= vfChartData; //基層改為double,這裡就掛了。
}
}

但如果當初就封裝起來,繼承類別只能利用getter的函式取資料,就算後來我底層要改double,我依然可以利用getter函式傳回一個float的類別(只是原本取資料的地方要從float轉為double再轉回float,頗令人無言),相關的子類別原本就是利用getter函式取資料,所以根本不用動。

改用getter的方式如下ex:
Class BaseChart //基層類別
{
private:
vector<float> vfChartData; //因新需求,將其改為double

protected:
vector<float>& vfChartData(){return vfChartData;}(註*)
void vfChartData(vector<float> vf ){vfChartData=vf;}
//改為double後,函式可以加工,個別轉型為float。
}

Class DerivedChart //繼承類別
{
void SetData{
vector<float> vfDerivedData;

vfChartData(vfDerivedData); //基層改為double,這裡不用動。
}
}

以下引述effective c++中的一段話:

封裝的重要性比你最初見到它時還要重要。如果你對客戶隱藏變數(也就是封裝他們),你可以確保class的約束條件總是獲得維護,因為只有成員函式可以影響他們。尤有進者,你保留了日後變更實作的權利。如果你不隱藏他們,你很快就會發現,即使擁有class原始碼,改變任何public事物的能力還是極端受到束縛,因為那會破壞太多客戶碼。public意味不封裝,而幾乎可以說,不封裝意味不可改變,特別是對被廣泛使用的classes而言。被廣泛使用的classes是最需要封裝的一個族群,因為他們最能夠從『改用一個較佳實作版本』中獲益。

protected與public的觀點一致。試想如果改變一個public變數,將影響使用他的客戶碼,這是個不可知的大量,那麼修改一個protected變數也一樣,他將影響繼承他的類別,這也是個不可知的大量。太多程式碼需要重寫意味著重新測試、重新撰寫文件、重新編譯。這可是誰都不想看到的事情。

但是實際撰寫又發生一個問題,繼承過來要用的變數太多了,一個一個加setter、getter函式,可是麻煩死了。所以此寫法對copy/paste寫法有抑制作用,因為要改很多XD。但是最近我灌了最新版的蕃茄,他有一個新的refector功能—encapsulate fields,可直接產生 getter、setter的程式碼。超棒的!推薦使用。寫了這麼長一篇,我想說的是我以後所有的變數都會宣告為private,看我程式的人不要覺得奇怪。要使用此變數者請封裝他,就這樣。

P.S.打完我又覺得我發神經,幹麼打那麼長的一篇。
又P.S.實際上港股指數走勢圖的寫法,卻不是這樣寫XD。

註:Getter需注意是傳回副本或將參考傳回去,蕃茄預設的功能是傳回副本,且需注意const。沒copy constructer的類別是無法傳回副本的。改型別後,新的getter函式名稱要與舊的函式不一樣(同名稱的函式不能傳回不同型態的值),如果舊的函式要改名可利用蕃茄refactor rename的功能。

留言

這個網誌中的熱門文章

勝券在握

其實這本書,感覺上寫的有點雜,比上一本講巴非特的書更難懂,兩個講的東西其實是一致的。投資原則便是先選產業,再選公司,慎選時機進場。只買了解的企業是價值投資一貫的原則。價值投資的書大概就先看到這裡了,彼得林區不知道是屬於那一類的,接下來大概會看這部份的書。暫時的目標是把杜金龍介紹的書單看完,真的還不少。接下來的投資會以巴菲特的方法來做,感覺上這比較適合我,練習把漲跌不當一回事,對我而言真的很重要。期權大概不會再玩了,買了以後一直在看漲跌,令人受不了。工作時都不能專心。 就價值投資人而言,真的不需要我們的產品,因為第一點就把我們程式特性打死,不理會股票市場的漲跌,這樣報價功能就沒什麼意義了,價值投資根本不需要技術分析,除非我們能提供相關價值投資的資訊,但我們基本分析真的很爛,看不到什麼資料。有機會我來思考一下價值投資到底要什麼資料,能不能把他寫成一個可運用的程式。 以下是我認為重要的書摘,其實這也只包含最後一章,我認為也只有這章值得做書摘。 巴非特相信使用短期價格來判斷一家公司的成功與否是愚蠢的。取而代之的是,他要公司向他報告因經濟實力成長所獲得的價值,一年一次,他固定檢查幾個變數: 初始的股東權益報酬率。 營運毛利、負債水準與資本支出需求的變化。 該公司的現金產生能力。 如果這些經濟指標正在進展,他知道長期下來,結果會反應在股價上。短期之內,股價所發生的是是不合常理的。 投資策略 不理會股票市場每日的漲跌 不擔心經濟情勢。 買下一家公司,而不是股票 管理企業的投資組合 巴非特原則 企業原則 這家企業是簡單且可以了解的 了解一家企業如何產生利潤的相關經濟活動。 這家企業的營運歷史是否穩定 他必須經得起時間的考驗。 這家企業的長期發展前景是否看好 市場特許權,五力分析 經營原則 經營者是否理性 理性的經營者將只會把多餘的現金,投資在那些產生較資本成本報酬率為高的計畫裡。 經營者對他的股東是誠實坦白的 報告時能知道營業部門如何營業,坦承失敗,了解公司的目的是使股東權益報酬率達到最大。 經營者是會盲從其他法人機構的行為 當心『其他公司也這麼做,一定沒問題』為自己行為辯護的經營者。衡量經營者競爭力的一個方法是,看他們如何運用自己的思考能力以避免依附群眾心理。 財務原則 把重點集中...

10/17部會心得

其實部會一開完,我就想寫了,只是最近沉迷於小說,直到今天才有開始動工的心情。 業務的報告部份就不要講了,一點都不感興趣,講的好像會大賣的樣子,薪水有增加再說啦! 技術方面, DQ 做的功能好像挺有意思的,不過感覺上沒人看出他的價值,不過我覺得最佳的 UI 還是 vs 2005 為主,如果要研發基底的 UI 我覺得要以類 VS 為目標。金融網的東西也令人興奮,我本來就覺得網頁的東西潛力無窮,雖然是抄的,不過覺得還不錯,網頁互抄比 AP 互抄容易多了,很多 AP 的功能要模擬出來,真的比想像中難太多了。雖然金融網聽到最後我睡著了,但我非常期待他下一版能帶來什麼。好吧!說一下我們這邊技術心得,看起來炫,但是我一點都不心動,因為我想不到這東西能增加我們產品的價值嗎? 這場部會最棒的是最後副總的報告,這是第一次瞭解整個產業環境與我們的應對方法,這樣我才清楚為什麼要成立那麼多非資訊本業部門,金融網成立的原因何在,產業鏈垂直整合的價值在哪裡。但是會像如規劃中的成功嗎?其實從旁觀察規劃與現在實際的運作,我抱的期望沒那麼大,不過這是有意思的夢,就看能不能實現囉! 不過在會中,我就想到一個我覺得可以配合上我們的產業架構,而且還不錯的商業模式,這也是我想寫這篇心得的原因。 在副總的報告中,提到金融網是為了提供一個入門的金融資訊,接觸最底層不付費的又想看金融資訊的民眾,其實我想到更進階的是接觸所有上網的人。而這功能結合 43thing 與財務規劃(參考 到底要賺多少錢才能退休呢? )你要作這些你想要做的事情(如遊學、旅遊)或退休,你到底要賺多少錢,然後開始洗腦光靠上班的死薪水是達不成這些目的的,所以要開始投資,投資如何規劃,就是要買我們的金融產品,一步一步引君入彀。這功能主要的對象就不只是想投資的人,而是所有的人,只要你心中有任何的夢想,而這夢想需要錢來達成,就需要這個工具。這就是把基底做的更大,個體經濟學常用的互補效應。所以這功能包含紀錄你要達成的夢想,財務管理包含薪資增加目標、稅務、相關的投資規劃與風險等。目標就是吸引所有人來理財、投資。 另一方面,我想倒也有一些人就是他沒有時間也沒有能力去學如何投資或操作股票,他們只想跟老師聽名牌,那這個就可以結合 blog 的功能來作,吸引一些老師來 blog 建立個人投資說明,開發一個跟單工具,這跟單工具可以比較所...

Slim Diray 3/6

飲食:早餐/火腿蛋吐司三明治+350g優酪乳;午餐/三杯雞飯;晚餐/鴨肉飯+500g巧克力牛奶。晚餐7點半前吃。 運動:無 體重: -10.6 公斤 (與前日輕0.4kg) 71.4 公斤 就寢時間:2:00 檢討:今天沒做運動,ㄟ到輕了0.4kg,吃的量跟昨天差不多,今天反而輕了,經驗談便是盤整不需理由,靜待突破反壓。 原本想低調,不想寫聯誼的。不過這場聯誼出乎意料的好玩,所以記錄一下。因為身為活動組組長的我,本來沒有啥動力安排什麼遊戲,剛開始覺得奇怪,Jim幹嘛安排在大魯閣,這樣聯誼要怎樣進行??果然自我介紹完,就換代幣去玩棒壘球了,而棒壘球,是一個人專心再打,大家就無聊的等位置,又Victor手傷沒辦法打,在一旁也不知道幹嘛。後來大家幾乎各自散開找位置打球或完投準,第一次提領的20枚代幣用完後,Jim就提議上去二樓玩,原來二樓也是用代幣玩的,終於感覺代幣沒有換太多,幾個小遊戲還蠻好玩的,中間我覺得最適合的聯誼遊戲是打桌球,裡面是投兩枚代幣,可以玩30分鐘,重點是兩個人在打,其他人就可以聊天,聯誼到那時刻終於有聊天的機會了,其實遊戲玩開後,聊天就比較自然一點,玩了兩輪桌球,也就是一小時,該聊的也都聊了吧,最後是打撞球,分隊打,大家技術都很爛,最後幾乎全靠自由球清檯。 而這場聯誼Jim找他的發光點了,對嘛!桌球系隊,不秀桌球的絕技,就浪費了,打球中間還教了靜郁幾手。對了!欣怡也是系隊的,我想他們很適合私底下切磋球技,哈!我有馥菁化的趨勢喔!相對今天我就比較低調了,多天的訓練似乎沒啥用,講話沒啥笑點,沒啥梗可以用,對話也不容易接下去,一整個遜掉了,而我自己對話,有很大的問題,眼神會亂飄,都是對話完畢,我才驚覺自己這個毛病又犯了,這樣感覺好像沒誠意。今天被講年記看起比較小,可是我每次照鏡子都覺得自己很糙老的,還說我娃娃臉!既然被這樣稱讚了,當然要回說妳看起來也比我小啊!嗯!沒玩配對遊戲,幾個之前預訂的聯誼獎勵,就不知道怎麼送了,我還是自肥好了。看大家有沒有機會發展下去,好像大家都無疾而終,只有我會主動再連絡,但是每個女的都連絡,又被講花心,嚇!我又沒對人家怎樣!奇怪!