面向物件知識點整理
面向物件考試簡述題整理
概述
1、 什麼是面向物件?
從程式設計方法的角度看,面向物件是一種新的程式設計範型(paradigm),其基本思想是使用物件、類、繼承、封裝、聚合、關聯、訊息、多型性等基本概念來進行程式設計。
面向物件方法是一種運用物件、類、繼承、封裝、聚合、關聯、訊息、多型性等概念來構造系統的軟體開發方法。
2、 面向物件基本思想。
從現實世界中客觀存在的事物出發來建立軟體系統
充分運用人類日常的思維方法
對問題空間進行自然分割,以更接近人類思維的方式建立問題域模型,以便對客觀實體進行結構模擬和行為模擬,從而使設計出的軟體儘可能直接地描述現實世界。
構造出模組化的、可重用的、維護性好的軟體,同時限制軟體的複雜性和降低開發維護費用。
3、面向物件主要特點
用類和物件作為系統的基本構成單位。物件對應問題域中的事物,其屬性與服務刻畫了事物的靜態特徵和動態特徵,它們之間的繼承關係、聚合關係、訊息和關聯如實地表達了問題域中事物之間實際存在的各種關係。
因此,無論系統的構成成分,還是通過這些成分之間的關係而體現的系統結構,都可直接地對映問題域。
第一章面向物件思想
1、物件是獨立存在的客觀事物,它由一組屬性和一組操作構成。屬性和操作是物件的兩大要素。屬性是物件靜態特徵的描述,操作是物件動態特徵的描述。
2、部分/整體關係中有兩種方式:組合和聚合。
3、█組合與聚合的區別
組合關係中部分和整體的關係很緊密。聚合關係中則比較鬆散,一個部分物件可以屬於幾個整體物件。
4、訊息和方法
在面向物件程式設計中,行為的啟動是通過將“訊息”傳遞給對此行為負責的代理(物件)來完成的。訊息對行為的要求進行編碼,並且隨著執行要求所需的附加資訊(引數)來一起傳遞。“接收器”就是訊息傳送的物件。如果接收器接受了訊息,那麼同時它也接受了訊息所包含的行為責任。然後,接受器響應訊息,執行相應的“方法”以實現要求。
5、訊息傳遞與過程呼叫
每一條訊息都有一個指定的接收器相對應;接收器就是訊息傳送的物件。過程呼叫沒有指定的接收器。
訊息的解釋由接收器決定,並且隨著接收器的不同而不同。
動態繫結。
6、資訊隱藏
作為某物件提供的服務的一個使用者,只需要知道物件將接受的訊息的名字。
不需要知道怎麼完成要求,需要執行哪些動作。
在接收到一條訊息後,物件會負責將該項任務完成。
7、責任
用責任來描述行為。A對行為的要求僅表明他所期望的結果,C可隨意選擇使用的方法來實現所期待的目標,並在此過程中不受A的干擾。
提高了抽象水平,物件更加獨立。
8、不干預原則
允許物件以任何它認為合適的不干涉其他物件的方式來完成任務,而不要干預它
9、類
根據抽象的原則對客觀事物進行歸納和劃分,只關注與當前目標相關的特徵,把具有相同特徵的事物歸為一個類。它是一個抽象的概念。類是具有相同屬性和相同操作(服務)的物件的集合。它包括屬性和操作。
10、類和例項
所有物件都是類的例項。
在響應訊息時呼叫何種方法由類的接收器來決定。
一個特定類的所有物件使用相同的方法來響應類似的訊息。
每一個物件都是某個類的例項。類是一組相似的物件 。
類是物件相關行為的儲存庫(repository)。即同一個類的所有物件都能執行同樣的動作。
11、改寫
將子類中某一方法取與父類方法相同的名稱,結合尋找方法的規則(當響應特定訊息時)實現改寫。
12、方法繫結與改寫
接收器搜尋並執行相應的方法以響應給定的訊息。
如果沒有找到匹配的方法,搜尋就會傳導到此類的父類。搜尋會在父類鏈上一直進行下去,直到找到匹配的方法,或者父類鏈結束。
如果能在更高類層次找到相同名稱的方法,所執行的方法就稱為改寫了繼承的行為。
13、多型
多型性是指一般類中定義的屬性和服務,在特殊類中不改變其名字,但通過各自不同的實現後,可以具有不同的資料型別或具有不同的行為。如不同花商送花方式。
多型可通過過載和類等級不同層次共享同一方法名字等方式來實現。
14、JAVA中的重寫/改寫和過載
重寫一般是指父類和子類之間,子類重寫了父類的一個方法,當然方法名是一樣的,而且不能改變父類方法的返回值,比如說父類是返回String,子類重寫了這個方法,想返回一個int,那是不行的,也得返回String。
過載是一個類裡面,寫了多了同名的方法,各個方法的返回值型別可以不一樣。區分過載方法可以通過引數列表的個數,型別和順序。
第二章抽象
1、抽象
抽象是指對於一個過程或者一件製品的某些細節有目的的隱藏,以便把其他方面、細節或者結構表達得更加清楚。(資訊隱藏) 抽象,是控制複雜性時最重要的工具。
第四章類和方法
1、什麼是封裝
避免重複的程式碼
保護類受到不必要的修改
2、介面
不提供實現
介面定義新型別,可以宣告變數
類的例項可以賦值給介面型別變數
3、向前定義
多個互相引用的類(相互遞迴)
Java全文掃描。C++向前定義
Java 語言在生成程式碼之前會掃描整個檔案,這樣,如果程式檔案的前面部分引用在檔案後面宣告的類,就不會產生任何衝突。其他的語言,例如 C++,會從前到後地依次處理程式檔案中的類和方法去。名稱在使用之前必須至少進行部分定義
4、靜態成員函式
成員函式。不能訪問非靜態成員。
無this
構造和解構函式不能為靜態成員。
第五章訊息、例項和初始化
1、訊息
使用訊息傳遞(message passing)這一術語來表示請求物件執行一項特定行為的動態過程
訊息總是傳遞給某個稱為接收器的物件
響應訊息所執行的行為不是固定不變的,它們根據接收器類的不同而不同
廣播,可響應可不響應
物件間相互請求或相互協作的途徑。
2、訊息傳遞語法
任何訊息傳遞表示式都有 3 個確定的部分,包括接收器(receiver,訊息傳遞的目的物件)訊息選擇器(message selector,表示待傳遞的特定的訊息文字)和用於響應訊息的引數(argument)。
響應行為隨接收器不同而不同。
3、靜態型別語言,動態型別語言
靜態:型別和變數聯絡在一起(Java,C++,C#,Pascal)
動態:變數看作名稱標識,型別和數值聯絡在一起。(SmatllTalk,Python)
動態型別語言與靜態型別語言之間的差異在於變數或數值是否具備型別這種特性。
4、靜態型別語言與動態型別語言在高效性與靈活性方面
在訊息傳遞這方面,靜態型別語言和動態型別語言之間存在顯著的差異。一方面,靜態型別語言在編譯時使用接收器的型別來檢查選擇器,以理解它所接收的訊息。另一方面,動態型別語言在編譯時則沒有辦法去核實這一訊息。
5、靜態類性語言
編譯時作出記憶體分配決定。不必執行時刻重新分配。
控制型別錯誤。
PlayingCard aCard;
aCard.someFunction();
6、動態型別語言
Function max(a,b){
if (a<b)
then returnb;
return a;
}
7、偽變數
大多數面嚮物件語言中,接收器並不出現在方法的引數列表中,而是隱藏於方法的定義之中。只有當必須從方法體內部去存取接收器的數值時,才會使用偽變數。
Java,C++:this
Eiffel:Current
Smalltalk,object-c:self
它不需要被宣告,也不能被更改。
8、物件自身引用
this隱含指向呼叫成員函式的物件。
9、Java:new僅建立陣列。陣列包含的物件必須獨立建立。
第八章繼承和替換
1、※擴充套件與簡化
繼承在程式語言中的含義如下:子類所具有的資料和行為總是作為與其相關的父類的屬性的擴充套件( extension) (即更大的集合)。子類具有父類的所有屬性以及其他屬性。另一方面,由於子類是父類的更加特殊(或受限制)的形式,在某種程度上,子類也是父類的收縮( contraction)。
這種把繼承作為一種擴充套件同時也作為一種收縮的思想,正是面向物件技術強大的原因,同時也會在正常的部署中引起混淆 。
2、繼承的作用
程式碼複用
概念複用。共享方法的定義。
3、通過(is-a)檢驗規則檢驗兩個概念是否為繼承關係
4、類中public和protected型別的成員,其子類能訪問;父類中private型別的成員,其子類不能訪問,只能自己類內部使用。
5、在靜態型別語言中父類和子類資料型別的關係?
①子類例項必須擁有父類的所有資料成員。
②子類的例項必須至少通過繼承實現父類所定義的所有功能。
這樣,在某種條件下,如果用子類例項來替換父類例項,那麼將會發現子類例項可以完全模擬父類的行為,二者毫無差異。
6、█替換原則
指如果類B是類A的子類,那麼在任何情況下都可以用類B來替換類A,而外界毫無察覺。
7、子型別*
指符合替換原則的子類關係。
區別於一般的可能不符合替換原則的子類關係
8、改寫
子類有時為了避免繼承父類的行為,需要對其進行改寫
語法上:子類定義一個與父類有著相同名稱且型別簽名相同的方法。
執行時:變數宣告為一個類,它所包含的值來自於子類,與給定訊息相對應的方法同時出現於父類和子類。
改寫與替換結合時,想要執行的一般都是子類的方法。
9、介面
Java介面是一系列方法的宣告,是一些方法特徵的集合,一個介面只有方法的特徵沒有方法的實現,因此這些方法可以在不同的地方被不同的類實現,而這些實現可以具有不同的行為(功能)。與類一樣,介面可以繼承於其他介面,甚至可以繼承於多個父介面。雖然繼承類和實現介面並不完全相同,但他們非常相似,因此使用繼承這一術語來描述這兩種行為。
第十章靜態行為和動態行為
1、靜態類和動態類
變數的靜態類是指用於宣告變數的類。靜態類在編譯時就確定下來,並且再也不會改變。
變數的動態類指與變數所表示的當前數值相關的類。動態類在程式的執行過程中,當對變數賦新值時可以改變。
對於靜態型別面向物件程式語言,在編譯時訊息傳遞表示式的合法性不是基於接收器的當前動態數值,而是基於接收器的靜態類來決定的。
2、向下造型(反多型)
做出數值是否屬於指定類的決定之後,通常下一步就是將這一數值的型別由父類轉換為子類。這一過程稱為向下造型,或者反多型,因為這一操作所產生的效果恰好與多型賦值的效果相反。
3、方法繫結
響應訊息時對哪個方法進行繫結是由接收器當前所包含的動態數值來決定的。
4、多型變數
如果方法所執行的訊息繫結是由最近賦值給變數的數值的型別來決定的,那麼就稱這個變數是多型的。Java,Smalltalk等變數都是多型的。
第十四章多型及軟體複用
1、※多型的形式
過載:(也稱為專用多型(ad hoc polymorphism))用於描述一個函式名稱(或者方法名稱)有多種不同實現方式的情況。通常可以在編譯時基於型別簽名來區分各個過載函式的名稱。
改寫:(或者包含多型(inclusionpolymorphism))是過載的一種特殊情況。只發生在有關父類與子類之間關係的上下文中。改寫方法具有相同名稱、相同的型別簽名。
多型變數(polymorphic variable):(或者賦值多型(assignment polymorphism))是指宣告為一種型別,但實際上卻可以包含另一種型別數值的變數。當多型變數用作引數時建立的函式將展現純多型(pure polymorphism)。//宣告與包含不同。
泛型(或模板)提供了一種建立通用工具的方法,可以在特定的場合將其特化。
2、最常用的軟體複用機制:繼承和組合。
3、組合
提供了一種利用已存在的軟體元件來建立新的應用程式的方法。
物件是資料(資料值)和行為的封裝。在通過使用組合複用已存在的資料抽象來建立新資料型別時,新資料結構的部分狀態只是已存在的資料結構的一個例項。
4、█組合與繼承的比較
組合是較為簡單的一種技術。優點是清楚地指示出在特定的資料結構中需要執行哪些操作。無需考慮列表類所定義的所有操作。
繼承無法知道一個方法是否可以合法地應用於集合。
使用繼承構建資料抽象的程式碼的簡潔性是繼承的一個優點
繼承無法防止使用者使用父類的方法來操縱新的資料結構:FirstElement
第十五章過載
1、過載是在編譯時執行的,而改寫是在執行時選擇的。
2、多個過程(或函式、方法)允許共享同一名稱,且通過該過程所需的引數數目、順序和型別來對它們進行區分。即使函式處於同一上下文,這也是合法的。
3、關於過載的解析,是在編譯時基於引數值的靜態型別完成的。不涉及執行時機制。
4、造型:自動型別轉換和強制型別轉換
自動型別轉換是一種隱式的型別轉換,它發生在無需顯式引用的程式中。強制型別轉換表示程式設計師所進行的顯式型別轉換。
5、x是y的父類
上溯造型
X a=new X();
Y b=new Y();
a=b; //將子類物件造型成父類物件,相當做了個隱式造型:a = (X)b;
下溯造型
X a=new X();
Y b=new Y();
X a1=b;
Y b1=(Y)a1 ;
6、作為轉換的替換
型別轉換:“型別的改變”,替換原則將引入一種傳統語言所不存在的另外一種形式的型別轉換。
發生在型別為子類的數值作為實參用於使用父類型別定義對應的形參的方法中時。
7、█匹配原則
找到所有可能進行呼叫的方法,即各個引數可以合法地賦值給各個引數型別的所有方法。如果找到一個在呼叫時可以完全匹配所使用的引數型別的方法,那麼就執行這個方法。
如果第一步所產生的集合中,某個方法的所有引數型別都可以賦值給集合中的另一個方法的所有引數型別,那麼就將第二個方法從集合中移走。重複以上操作,直至無法實現進一步的縮減為止。
如果只剩下一個方法,那麼這個方法就非常明確了,呼叫這個方法即可。如果剩餘的方法不止一個,那麼呼叫就產生歧義了,此時編譯器將報告錯誤。
第十六章改寫
1、如果子類的方法具有與父類的方法相同的名稱和型別簽名,稱子類的方法改寫了父類的方法。
2、改寫可看成是過載的一種特殊情況。
由於過載也涉及一個方法名稱和兩個或更多個方法體
3、█改寫和過載的差異
①對於改寫來說,方法所在的類之間必須符合父類/子類繼承關係,而對於簡單的過載來說,並無此要求。
②如果發生改寫,兩個方法的型別簽名必須匹配。
③過載方法總是獨立的,而對於改寫的兩個方法,有時會結合起來一起實現某種行為。
④過載通常是在編譯時解析的,而改寫則是一種執行時機制。對於任何給定的訊息,都無法預言將會執行何種行為,而只有到程式實際執行的時候才能對其進行確定。
4、改寫並不能改變方法的可存取性。
如果一個方法在父類中為public,那麼不允許在子類中將該方法宣告為private。反之亦然。
5、█代替與改進——兩種不同的關於改寫的解釋方式
代替(replacement):在程式執行時,實現代替的方法完全覆蓋父類的方法。即,當操作子類例項時,父類的程式碼完全不會執行。
改進(refinement):實現改進的方法將繼承自父類的方法的執行作為其行為的一部分。這樣父類的行為得以保留且擴充。
這兩種形式的改寫都很有用,並且經常在一種程式語言內同時出現
如:幾乎所有的語言在建構函式中都使用改進語義。即,子類建構函式總是呼叫父類的建構函式,來保證父類的資料欄位和子類的資料欄位都能夠正確地初始化化。
第十七章多型變數
1、多型變數是指可以引用多種物件型別的變數。
這種變數在程式執行過程可以包含不同型別的數值。
對於動態型別語言,所有的變數都可能是多型的。
對於靜態型別語言,多型變數則是替換原則的具體表現。
2、多型變數形式
簡單變數
接收器變數
純多型(多型方法)
3、多型變數在框架中的作用
多型接收器功能的強大之處表現在訊息傳遞與改寫相結合時。這種結合是軟體框架開發的關鍵。
一般框架系統中的方法分為兩大類:
①在父類中定義基礎方法,被多個子類所繼承,但不被改寫;
②父類定義了關於多種活動的方法,但要延遲到子類才實現。
4、接收器變數多型性的展現
當執行基礎方法時,接收器實際上儲存的是一個子類例項的數值。
當執行一個改寫方法時,執行的是子類的方法,而不是父類的方法。
第二十一章框架
1、框架開發的一個重要基礎是以完全不同的兩種方式來使用繼承—複用、特化
2、類的方法可以分為兩大類
基本方法:它定義於父類,通過繼承但卻不對其改寫的方式成為子類的一部分。體現了對問題的現存的解決方案。程式碼複用。
特化方法:為了適合於子類的特定環境,改變了其在父類中的行為。用於特定應用的解決方案。概念複用。
面向物件的設計原則
1、設計目標
可擴充套件性(Extensibility):新功能易加入系統。
靈活性(Flexibility):允許程式碼修改平穩發生,不會涉及很多其他模組。
可插入性(Pluggability):容易將一個類換為另一個具有同樣介面的類。
2、軟體複用重要性
較高的生產率
較高的軟體質量
恰當使用複用,可改善系統的可維護性
3、抽象化和繼承:使概念和定義可複用
多型:使實現和應用可複用
抽象化和封裝:可保持和促進系統的可維護性
4、面向物件設計中,可維護性複用是以設計原則和設計模式為基礎的。
5、面向物件設計原則
開閉原則OCP:Open-ClosedPrinciple
里氏替換原則LSP:LiskovSubstitution Principle
依賴倒轉原則DIP:DependencyInversion Principle
介面隔離原則ISP:InterfaceSegregation Principle
組合複用原則CRP:CompositoinResuse Principle
迪米特法則LoD:Lawof Demeter
單一職責原則(SRP)
6、開閉原則
軟體組成實體應該是對擴充套件可擴充套件的,但是對修改是關閉的。
7、依賴倒轉原則
抽象不應當依賴於細節,細節應當依賴於抽象。
8、█使用介面的優點
Client不必知道其使用物件的具體所屬類。
一個物件可以很容易地被(實現了相同介面的)的另一個物件所替換。
物件間的連線不必硬繫結(hardwire)到一個具體類的物件上,因此增加了靈活性。
鬆散耦合 (loosens coupling)。
增加了重用的可能性。
提高了(物件)組合的機率,因為被包含物件可以是任何實現了一個指定介面的類。
9、組合複用原則
組合優先原則:優先使用(物件)組合,而非(類)繼承
10、█組合的優點
容器類僅能通過被包含物件的介面來對其進行訪問。
“黑盒”複用,因為被包含物件的內部細節對外是不可見。
封裝性好。
實現上的相互依賴性比較小。
每一個類只專注於一項任務。
通過獲取指向其它的具有相同型別的物件引用,可以在執行期間動態地定義(物件的)組合。
11、█組合的缺點
從而導致系統中的物件過多。
為了能將多個不同的物件作為組合塊(composition block)來使用,必須仔細地對介面進行定義。
12、█繼承的優點
容易進行新的實現,因為其大多數可繼承而來。
易於修改或擴充套件那些被複用的實現。
13、█繼承缺點
破壞了封裝性,因為這會將父類的實現細節暴露給子類。
“白盒”複用,因為父類的內部細節對於子類而言通常是可見的。
當父類的實現更改時,子類也不得不會隨之更改。
從父類繼承來的實現將不能在執行期間進行改變。