參考牢記面向?qū)ο笪鍌€基本原則跌宛;深入理解Java中的重寫和重載酗宋;
Java中方法的重寫與成員變量的隱藏;深入理解Java中的組合和繼承
有一些個人看法疆拘,如有錯誤歡迎指正
一蜕猫、三大基本特征
Java是一個面向?qū)ο蟮恼Z言。封裝哎迄、繼承回右、多態(tài)是面向?qū)ο蟮娜齻€特征隆圆。
封裝
意義在于保護和隱藏。隱藏對象的屬性和實現(xiàn)細節(jié)翔烁,僅對外公開訪問方法渺氧,且控制訪問級別。Java用類實現(xiàn)封裝蹬屹,用封裝實現(xiàn)高內(nèi)聚(內(nèi)部關(guān)聯(lián))和低耦合(外部關(guān)聯(lián))
繼承
意義在于復(fù)用阶女。Java的復(fù)用技術(shù)有繼承、組合哩治、代理秃踩,三種表現(xiàn)形式。
子類繼承父類业筏,是is-a
關(guān)系憔杨,并且父類是已知的類,編譯時就確定了蒜胖。破壞了封裝性,子類知道父類的細節(jié)寻狂,并且可以隨意調(diào)用(除private)朋沮。但不是父類的什么都可以繼承和重寫,父類的靜態(tài)域只能被繼承樊拓,不能被重寫,而是被隱藏蒂胞,即調(diào)用的只能是父類的屬性和方法条篷。所以子類與父類的耦合性會非常高。由于子類可以直接使用父類實現(xiàn)的方法鸿染,對子類來說稚瘾,一旦從父類那里繼承卻沒有Override的部分改變了,子類也必須做相應(yīng)改變丢烘。
組合,是一種拼裝掸刊,擁有has-a
關(guān)系忧侧。即A類內(nèi)有聲明為B的成員牌芋。B可以是接口,所以在編譯時肯夏,還不知道具體要用到哪個類犀暑。并且調(diào)用都是用B.方法名
調(diào)用的,實現(xiàn)細節(jié)由B決定徊都,運行時才知道具體執(zhí)行的類广辰,且改變也不會影響A,因為A只知道傳入?yún)?shù)和預(yù)期結(jié)果袱耽,并不關(guān)心細節(jié)干发。
雖然組合看起來更優(yōu)秀史翘,在都可以使用時,推薦用組合解耦合必峰。但是有些情況(需要重寫的時候)還是更加適合用繼承:
繼承要慎用吼蚁,其使用場合僅限于你確信使用該技術(shù)有效的情況。一個判斷方法是粒蜈,問一問自己是否需要從新類向基類進行向上轉(zhuǎn)型旗国。如果是必須的,則繼承是必要的度硝。反之則應(yīng)該好好考慮是否需要繼承寿冕。《Java編程思想》
只有當子類真正是超類的子類型時存捺,才適合用繼承曙蒸。換句話說,對于兩個類A和B肖油,只有當兩者之間確實存在
is-a
關(guān)系的時候臂港,類B才應(yīng)該繼續(xù)類A∠馗ぃ《Effective Java》
多態(tài)
目的也是為了解耦合佑力。指允許不同類的對象對同一消息做出響應(yīng)。同一個函數(shù)調(diào)用暴拄,可以自動采用不同的行為方式乖篷。
? 分為編譯時多態(tài)(參數(shù)數(shù)量不同)和運行時多態(tài)(運行時實際調(diào)用者不同)透且。還有一種說法是,編譯時已經(jīng)確定的重載鲸沮,不能算作一種多態(tài)的方式。那按這種說法就只有運行時多態(tài)一種稱為多態(tài)日熬。
? 編譯時多態(tài)是方法的重載(Overload)肾胯,在編譯時根據(jù)參數(shù)列表選擇方法名一致的方法中,用哪一個(JVM方法簽名=方法名+參數(shù)列表)毕荐。
? 運行時多態(tài)是重寫(Override)運用的技術(shù)叫動態(tài)綁定(dynamic binding)即調(diào)用者聲明為接口或父類(可以是普通的類也可以是抽象類)艳馒,只有執(zhí)行到這里才知道具體調(diào)用的是哪個類實現(xiàn)的那個方法弄慰。方法簽名完全一致,所以會覆蓋掉父類的實現(xiàn)什往,即自動向上轉(zhuǎn)型慌闭。
二、五大基本原則
五大基本原則分別是:單一職責(同一件事用同一個類省古,用參數(shù)來區(qū)分細節(jié))丧失、開放封閉(一旦開發(fā)好一個功能即能獨立運轉(zhuǎn),新的功能隨時能追加利花,但與之無關(guān))、Liskov替換(動態(tài)綁定不影響調(diào)用者功能)、依賴倒置(接口和實現(xiàn)分離挠乳,調(diào)用者聲明只用接口)、接口隔離(避免胖接口盟蚣,JDK8的Defult就在緩解胖接口問題)
單一職責原則(Single-Resposibility Principle)
其核心思想為:一個類,最好只做一件事屎开,只有一個引起它的變化马靠。單一職責原則可以看做是低耦合、高內(nèi)聚在面向?qū)ο笤瓌t上的引申逞度。通常意義下的單一職責,就是指只有一種單一功能档泽,不要為類實現(xiàn)過多的功能點馆匿,以保證實體只有一個引起它變化的原因燥滑。
開放封閉原則(Open-Closed principle)
開放封閉原則主要體現(xiàn)在兩個方面
對擴展開放,意味著有新的需求或變化時腔稀,可以對現(xiàn)有代碼進行擴展,以適應(yīng)新的情況焊虏。
對修改封閉秕磷,意味著類一旦設(shè)計完成,就可以獨立完成其工作疏尿,而不要對其進行任何嘗試的修改易桃。
Liskov替換原則(Liskov-Substituion Principle)
其核心思想是:子類必須能夠替換其基類。這一思想體現(xiàn)為對繼承機制的約束規(guī)范敌呈,將基類替換為子類,程序的行為不會發(fā)生任何變化磕洪。同時析显,這一約束反過來則是不成立的,子類可以替換基類谷异,但是基類不一定能替換子類。 ? 實現(xiàn)的方法是面向接口編程:將公共部分抽象為基類接口或抽象類寓落,通過Extract Abstract Class荞下,在子類中通過覆寫父類的方法實現(xiàn)新的方式支持同樣的職責尖昏。 ? Liskov替換原則能夠保證系統(tǒng)具有良好的拓展性,同時實現(xiàn)基于多態(tài)的抽象機制抽诉,能夠減少代碼冗余,避免運行期的類型判別河绽。
依賴倒置原則(Dependecy-Inversion Principle)
其核心思想是:高層模塊不依賴于底層模塊耙饰,二者都同依賴于抽象纹份; ? 我們知道,依賴一定會存在于類與類蔓涧、模塊與模塊之間。當兩個模塊之間存在緊密的耦合關(guān)系時篷扩,最好的方法就是分離接口和實現(xiàn):在依賴之間定義一個抽象的接口使得高層模塊調(diào)用接口瞻惋,而底層模塊實現(xiàn)接口的定義厦滤,以此來有效控制耦合關(guān)系歼狼,達到依賴于抽象的設(shè)計目標羽峰。
接口隔離原則(Interface-Segregation Principle)
其核心思想是:使用多個小的專門的接口添瓷,而不要使用一個大的總接口。 具體而言鳞贷,接口隔離原則體現(xiàn)在:接口應(yīng)該是內(nèi)聚的,應(yīng)該避免“胖”接口惰聂。一個類對另外一個類的依賴應(yīng)該建立在最小的接口上咱筛,不要強迫依賴不用的方法,這是一種接口污染溉愁。 ? 接口有效地將細節(jié)和抽象隔離拐揭,體現(xiàn)了對抽象編程的一切好處奕塑,接口隔離強調(diào)接口的單一性。而胖接口存在明顯的弊端爵川,會導(dǎo)致實現(xiàn)的類型必須完全實現(xiàn)接口的所有方法寝贡、屬性等;
分離的手段主要有以下兩種:
委托分離碟案,通過增加一個新的類型來委托客戶的請求颇蜡,隔離客戶和接口的直接依賴辆亏,但是會增加系統(tǒng)的開銷扮叨。
多重繼承分離领迈,通過接口多繼承來實現(xiàn)客戶的需求狸捅,這種方式是較好
JDK8允許接口有默認實現(xiàn),defult方法磁浇。它的出現(xiàn)可以緩解胖接口問題置吓。聲明為defult的方法后鞍匾,方法可以有花括號,里面可以有默認實現(xiàn)构拳。default方法子類可以重寫也可以不重寫梁棠。
謝謝觀看,如果有用麻煩點個喜歡凫海,對我是莫大的鼓勵男娄。