繼承的設(shè)計(jì)技巧(學(xué)習(xí) Java 編程語(yǔ)言 055)

  1. 將公共操作和字段放在超類

    這就是為什么將姓名字段放在 Person 類中,而沒(méi)有將它放在 Employee 和 Student類中的原因愚战。

  2. 不要使用受保護(hù)的字段

    有些程序員認(rèn)為,將大多數(shù)的實(shí)例字段定義為 protected 是一個(gè)不錯(cuò)的主意齐遵,“以防萬(wàn)一”寂玲,這樣子類能夠在需要的時(shí)候直接訪問(wèn)這些字段。然而梗摇,protected 機(jī)制并不能夠帶來(lái)更多的保護(hù)拓哟,這有兩方面的原因:
    1. 子類集合是無(wú)限制的,任何一個(gè)人都能夠由你的類派生一個(gè)子類伶授,然后編寫(xiě)代碼以直接訪問(wèn) protected 實(shí)例字段断序,從而破壞了封裝性。
    1. 在 Java 中糜烹,在同一個(gè)包中的所有類都可以訪問(wèn) proteced 字段违诗,而不管它們是否為這個(gè)類的子類。

    不過(guò)疮蹦,protected 方法對(duì)于指示那些不提供一般用途而應(yīng)在子類中重新定義的方法很有用诸迟。

  3. 使用繼承實(shí)現(xiàn) “is-a” 關(guān)系

    使用繼承很容易達(dá)到節(jié)省代碼的目的,但有時(shí)候也被人們?yōu)E用。例如阵苇,假設(shè)需要定義一個(gè)鐘點(diǎn)工(Contractor)類壁公。鐘點(diǎn)工有姓名和雇傭日期,但是沒(méi)有工資绅项。他們按小時(shí)計(jì)薪紊册,并且不會(huì)因?yàn)橥涎訒r(shí)間而獲得加薪。這似乎在誘導(dǎo)人們由 Employee 派生出子類 Contractor快耿,然后再增加一個(gè) hourlyWage 字段囊陡。

    public class Contractor extends Employee {
    ?private double hourlyWage;
    ?...
    }

    不過(guò),這并不是一個(gè)好主意润努。因?yàn)檫@樣一來(lái)关斜,每個(gè)鐘點(diǎn)對(duì)象中都包含了工資和時(shí)薪這兩個(gè)字段。在實(shí)現(xiàn)打印時(shí)薪或稅單的方法時(shí)铺浇,這會(huì)帶來(lái)無(wú)盡的麻煩痢畜,與不采用繼承相比,使用繼承實(shí)現(xiàn)最后反而會(huì)寫(xiě)多寫(xiě)很多代碼鳍侣。

    鐘點(diǎn)工與員工之間不屬于“ is-a” 關(guān)系丁稀。鐘點(diǎn)工不是特殊的員工。

  4. 除非所有繼承的方法都有意義倚聚,否則不要使用繼承

    假設(shè)想編寫(xiě)一個(gè) Holiday 類线衫。毫無(wú)疑問(wèn),每個(gè)假日也是一日惑折,并且一天可以用 GregorianCalendar 類的實(shí)例表示授账,因此可以使用繼承。
    class Holiday extends CregorianCalendar { . . .}
    很遺憾惨驶,在繼承的操作中白热,假日集合不是封閉的。在 GregorianCalendar 中有一個(gè)公有方法 add粗卜,可以將假日轉(zhuǎn)換成非假日:
    Holiday Christmas;
    Christmas.add(Calendar.DAY_OF_MONTH, 12);
    因此屋确,繼承對(duì)于這個(gè)例子來(lái)說(shuō)并不太適宜。
    需要指出续扔,如果擴(kuò)展 LocalDate 就不會(huì)出現(xiàn)這個(gè)問(wèn)題攻臀。由于這個(gè) LocalDate 類是不可變的,所以沒(méi)有任何方法能夠把假日變成非假日纱昧。

  5. 在覆蓋方法時(shí)刨啸,不要改變預(yù)期的行為

    替換原則不僅應(yīng)用于語(yǔ)法,更重要的是识脆,它也適用于行為设联。在覆蓋一個(gè)方法的時(shí)候加匈,不應(yīng)該毫無(wú)原由地改變它的行為。就這一點(diǎn)而言仑荐,編譯器不會(huì)提供任何幫助,即編譯器不會(huì)檢查重新定義的方法是否有意義纵东。例如粘招,可以重新定義 Holiday 類中的 add 方法來(lái)“修正”這個(gè)方法的問(wèn)題,可能什么也不做偎球,或者拋出一個(gè)異常洒扎,或者是前進(jìn)到下一個(gè)假日。
    然而衰絮,這樣一個(gè)“修正”違反了替換原則袍冷。對(duì)于以下語(yǔ)句序列
    int d1 = x.get(Calendar.DAY_OF_MONTH);
    x.add(Calendar.DAY_OF_MONTH, 1);
    int d2 = x.get(Calendar.DAY_OF_MONTH);
    System.out.println(d2 - d1);
    不管 x 的類型是 CregorianCalendar 還是 Holiday,執(zhí)行上述語(yǔ)句后都應(yīng)該得到預(yù)期行為猫牡。

    當(dāng)然胡诗,這個(gè)難題。理智和不理智的人們可能就預(yù)期行為是什么爭(zhēng)論不休淌友。煌恢。例如,有些人爭(zhēng)論說(shuō)震庭,置換原則要求 Manager.equals 忽略 bonus 字段瑰抵,因?yàn)?Employee.equals 就忽略了這個(gè)字段。實(shí)際上器联,憑空討論這些問(wèn)題毫無(wú)意義二汛。歸根結(jié)底,關(guān)鍵在于在子類中覆蓋方法時(shí)拨拓,不要偏離最初的設(shè)計(jì)想法肴颊。

  6. 使用多態(tài),而不要使用類型信息

    只要看到類似下面的代碼
    if(x is of type 1) {
    ?action1(x);
    }else if(x is of type 2) {
    ?action2(x);
    }
    都應(yīng)該考慮使用多態(tài)性千元。
    action1 與 action2 表示的是相同的概念嗎苫昌?如果是相同的概念,就應(yīng)該為這個(gè)概念定義一個(gè)方法幸海,并將其放置在兩個(gè)類型的超類或接口中祟身,然后,就可以調(diào)用
    x.action();
    使用多態(tài)性固有的動(dòng)態(tài)分派機(jī)制執(zhí)行正確的動(dòng)作物独。

    使用多態(tài)方法或接口實(shí)現(xiàn)的代碼比使用多個(gè)類型檢測(cè)的代碼更易于維護(hù)和擴(kuò)展袜硫。

  7. 不要濫用反射

    反射機(jī)制使人們可以在運(yùn)行時(shí)查看字段和方法,從而編寫(xiě)出更具有通用性的程序挡篓。這種功能對(duì)于編寫(xiě)系統(tǒng)程序及其重要婉陷,但是通常不適用于編寫(xiě)應(yīng)用程序帚称。反射是很脆弱的,如果使用反射秽澳,編譯器將無(wú)法幫助你查找編程錯(cuò)誤闯睹,因此只有在運(yùn)行時(shí)才會(huì)發(fā)現(xiàn)錯(cuò)誤并導(dǎo)致異常。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末担神,一起剝皮案震驚了整個(gè)濱河市楼吃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌妄讯,老刑警劉巖孩锡,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異亥贸,居然都是意外死亡躬窜,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門炕置,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)荣挨,“玉大人,你說(shuō)我怎么就攤上這事讹俊】殉粒” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵仍劈,是天一觀的道長(zhǎng)厕倍。 經(jīng)常有香客問(wèn)我,道長(zhǎng)贩疙,這世上最難降的妖魔是什么讹弯? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮这溅,結(jié)果婚禮上组民,老公的妹妹穿的比我還像新娘。我一直安慰自己悲靴,他們只是感情好臭胜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著癞尚,像睡著了一般耸三。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上浇揩,一...
    開(kāi)封第一講書(shū)人閱讀 51,258評(píng)論 1 300
  • 那天仪壮,我揣著相機(jī)與錄音,去河邊找鬼胳徽。 笑死积锅,一個(gè)胖子當(dāng)著我的面吹牛爽彤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播缚陷,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼适篙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了箫爷?” 一聲冷哼從身側(cè)響起匙瘪,我...
    開(kāi)封第一講書(shū)人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蝶缀,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體薄货,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡翁都,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谅猾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柄慰。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖税娜,靈堂內(nèi)的尸體忽然破棺而出坐搔,到底是詐尸還是另有隱情,我是刑警寧澤敬矩,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布概行,位于F島的核電站,受9級(jí)特大地震影響弧岳,放射性物質(zhì)發(fā)生泄漏凳忙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一禽炬、第九天 我趴在偏房一處隱蔽的房頂上張望涧卵。 院中可真熱鬧,春花似錦腹尖、人聲如沸柳恐。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)乐设。三九已至,卻和暖如春断凶,著一層夾襖步出監(jiān)牢的瞬間伤提,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工认烁, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肿男,地道東北人介汹。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像舶沛,于是被迫代替她去往敵國(guó)和親嘹承。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容