什么是多態 1.面向對象的三大特性:封裝、繼承、多態。從一定角度來看,封裝和繼承幾乎都是為多態而準備的。這是我們最后一個概念,也是最重要的知識點。 2.多態的定義:指允許不同類的對象對同一消息做出響應。即同一消息可以根據發送對象的不同而采用多種不同的行為方式。(發送消息就是函數調用) 3.實現多態的技術稱為:動態綁定(dynamic binding),是指在執行期間判斷所引用對象的實際類型,根據其實際的類型調用其相應的方法。 4.多態的作用:消除類型之間的耦合關系。 5.現實中,關于多態的例子不勝枚舉。 下面是多態存在的三個必要條件,要求大家做夢時都能背出來! 多態存在的三個必要條件 一、要有繼承; 二、要有重寫; 三、父類引用指向子類對象。多態的好處: 1.可替換性(substitutability)。多態對已存在代碼具有可替換性。例如,多態對圓Circle類工作,對其他任何圓形幾何體,如圓環,也同樣工作。 2.可擴充性(extensibility)。多態對代碼具有可擴充性。增加新的子類不影響已存在類的多態性、繼承性,以及其他特性的運行和操作。 實際上新加子類更容易獲得多態功能。例如,在實現了圓錐、半圓錐以及半球體的多態基礎上,很容易增添球體類的多態性。 3.接口性(interface-ability)。多態是超類通過方法簽名,向子類提供了一個共同接口,由子類來完善或者覆蓋它而實現的。 4.靈活性(flexibility)。它在應用中體現了靈活多樣的操作,提高了使用效率。 5.簡化性(simplicity)。多態簡化對應用軟件的代碼編寫和修改過程,尤其在處理大量對象的運算和操作時,這個特點尤為突出和重要。 Java中多態的實現方式:接口實現,繼承父類進行方法重寫,同一個類中進行方法重載。 1.Java中除了static和final方法外,其他所有的方法都是運行時綁定的。private方法都被隱式指定為final的,因此final的方法不會在運行時綁定。 當在派生類中重寫基類中static、final、或private方法時,實質上是創建了一個新的方法。 2.在派生類中,對于基類中的private方法,最好采用不同的名字。 3.包含抽象方法的類叫做抽象類。注意定義里面包含這樣的意思,只要類中包含一個抽象方法,該類就是抽象類。抽象類在派生中就是作為基類的角色,為不同的子類提供通用的接口。 4.對象清理的順序和創建的順序相反,當然前提是自己想手動清理對象,因為大家都知道Java垃圾回收器。 5.在基類的構造方法中小心調用基類中被重寫的方法,這里涉及到對象初始化順序。 6.構造方法是被隱式聲明為static方法。 7.用繼承表達行為間的差異,用字段表達狀態上的變化。 在JAVA中有兩種多態是指:運行時多態和編譯時多態。 關于類的多態性簡介如下: 多態性是面向對象的核心特征之一,類的多態性提供類中成員設計的靈活性和方法執行的多樣性. 1、類多態性表現 (1)方法重載 重載表現為同一個類中方法的多態性.一個類生命多個重載方法就是為一種功能提供多種實現.編譯時,根據方法實際參數的數據類型\個數和次序,決定究竟應該執行重載方法中的哪一個. (2)子類重定義從父類繼承來的成員 當子類從父類繼承來的成員不適合子類時,子類不能刪除它們,但可以重定義它們,使弗雷成員適應子類的新需求.子類重定義父類成員,同名成員在父類與子類之間表現出多態性, 父類對象引用父類成員,子類對象引用子類成員,不會產生沖突和混亂. 子類可重定義父類的同名成員變量,稱子類隱藏父類成員變量.子類也可以重定義父類的同名成員方法,當子類方法的參數列表與父類方法參數列表完全相同時, 稱為子類方法覆蓋(override)父類方法。覆蓋父類方法時,子類方法的訪問權限不能小于父類方法的權限。 由于Object類的equals()方法比較兩個對象的引用是否相等而不是值是否相等,因此一個類要覆蓋Object類的equals()方法,提供本類兩個對象比較相等方法. 覆蓋表現為父類與子類之間方法的多態性.java 尋找執行方法的原則是:從對象所屬的類開始,尋找匹配的方法執行,如果當前類中沒有匹配的方法, 則逐層向上依次在父類或祖先類中尋找匹配方法,直到Object類. 2、super 引用 在子類的成員方法中,可以使用代詞super引用父類成員.super引用的語法如下: super([參數列表]) //在子類的構造方法體中,調用父類的構造方法 super.成員變量 //當子類隱藏父類成員變量時,引用父類同名成員變量 super.成員方法([參數列表]) //當子類覆蓋父類成員方法時,調用父類同名成員方法 *注意:super引用沒有單獨使用的語法 3、多態性有兩種: 1)編譯時多態性 對于多個同名方法,如果在編譯時能夠確定執行同名方法中的哪一個,則稱為編譯時多態性. 2)運行時多態性 如果在編譯時不能確定,只能在運行時才能確定執行多個同名方法中的哪一個,則稱為運行時多態性 方法覆蓋表現出兩種多態性,當對象獲得本類實例時,為編譯時多態性,否則為運行時多態性,例如: XXXX x1 = new XXXX(參數列表); //對象獲得本類實例,對象與其引用的實例類型一致 XXX xx1 = new XXX(參數列表); x1.toString(); //編譯時多態性,執行XXX類的方法. xx1.toString(); //編譯時多態性,執行XXXX類覆蓋的方法. XXXX為XXX的父類. 由于子類對象既是父類對象,父類對象與子類對象之間具有賦值相容性,父類對象能夠被賦值為子類對象.例如, XXXX x2 = new XXX(參數列表); //父類對象獲得子類實例,子類對象即是父類對象 x2.toString(); //運行時多態 x2聲明為父類對象卻獲得子類XXX的實例,那么x2.toString()究竟執行父類方法還是執行子類覆蓋的方法呢? 這分為兩種情況: 取決于子類是否覆蓋父類方法.如果子類覆蓋父類方法,則執行子類方法; 如果沒有覆蓋,則執行父類方法. 在編譯時,僅僅依據對象所屬的類,系統無法確定到底應該執行那個類的方法,只有運行時才能確定,因此這是運行時多態. 父類對象并不能執行所有的子類方法,只能執行那些父類中聲明\子類覆蓋的子類方法. 在這樣一個體系中,多態表現出多種形式的能力。通用多態引用有相同結構類型的大量對象,他們有著共同的特征。特定的多態涉及的是小部分沒有相同特征的對象。 四種多態可做以下描述:強制的:一種隱式做類型轉換的方法。重載的:將一個標志符用作多個意義。參數的:為不同類型的參數提供相同的操作。包含的:類包含關系的抽象操作。 我將在講述子類型多態前簡單介紹一下這幾種多態。強制的多態強制多態隱式的將參數按某種方法,轉換成編譯器認為正確的類型以避免錯誤。在以下的表達式中,編譯器必須決定二元運算符‘+’所應做的工作:2.0 + 2.02.0 + 22.0 + "2" 第一個表達式將兩個double的操作數相加;Java中特別聲明了這種用法。 第二個表達式將double型和int相加。Java中沒有明確定義這種運算。不過,編譯器隱式的將第二個操作數轉換為double型,并作double型的加法。 做對程序員來說十分方便,否則將會拋出一個編譯錯誤,或者強制程序員顯式的將int轉換為double。 第三個表達式將double與一個String相加。Java中同樣沒有定義這樣的操作。所以,編譯器將double轉換成String類型,并將他們做串聯。 強制多態也會發生在方法調用中。假設類Derived繼承了類Base,類C有一個方法,原型為m(Base),在下面的代碼中,編譯器隱式的將 Derived類的對象derived轉化為Base類的對象。 這種隱式的轉換使m(Base)方法使用所有能轉換成Base類的所有參數。 C c = new C(); Derived derived = new Derived(); c.m( derived ); 并且,隱式的強制轉換,可以避免類型轉換的麻煩,減少編譯錯誤。當然,編譯器仍然會優先驗證符合定義的對象類型。 重載的多態重載允許用相同的運算符或方法,去表示截然不同的意義。‘+’在上面的程序中有兩個意思:兩個double型的數相加;兩個串相連。另外還有整型相加, 長整型,等等。這些運算符的重載,依賴于編譯器根據上下文做出的選擇。以往的編譯器會把操作數隱式轉換為完全符合操作符的類型。雖然Java明確支持重 載,但不支持用戶定義的操作符重載。Java支持用戶定義的函數重載。一個類中可以有相同名字的方法,這些方法可以有不同的意義。這些重載的方法中,必須滿足參數數目不同,相同位置上的參數類型不同。這些不同可以幫助編譯器區分不同版本的方法。編譯器以這種唯一表示的特征來表示不同的方法,比用名字表示更為有效。據此,所有的多態行為都能編譯通過。強制和重載的多態都被分類為特定的多態,因為這些多態都是在特定的意義上的。這些被劃入多態的特性給程序員帶來了很大的方便。強制多態排除了麻煩的類型和編譯錯誤。重載多態像一塊糖,允許程序員用相同的名字表示不同的方法,很方便。 參數的多態參數多態允許把許多類型抽象成單一的表示。例如,List抽象類中,描述了一組具有同樣特征的對象,提供了一個通用的模板。你可以通過指定一種類型以重 用這個抽象類。這些參數可以是任何用戶定義的類型,大量的用戶可以使用這個抽象類,因此參數多態毫無疑問的成為最強大的多態。 包含的多態包含多態通過值的類型和集合的包含關系實現了多態的行為.在包括Java在內的眾多面向對象語言中,包含關系是子類