導航:首頁 > 源碼編譯 > 編譯期多態和運行期多態的優缺點

編譯期多態和運行期多態的優缺點

發布時間:2022-09-21 04:30:57

1. java多態問題

應該是你沒有完全理解,編譯時多態其實是較淺層次的,並不是多態的精髓所在,運行時多態才是精髓所在。
編譯時多態其實完全可以用不同的方法名來解決,編程者在寫代碼的時候,就完全知道該調用哪一個方法,這其實並不是多態,而是一種語法現象,讓你可以把相似功能但參數不同的方法,可以寫成同樣的名字,寫的時候不必為相似功能的一系列函數起名而絞盡腦汁,閱讀時一看幾個方法名字都一樣,哦,重載了。
真正意義上的多態,是使用虛擬調用的技術來實現,確保你對象名.方法名,可以在運行時調用到正確的方法。
真正意義的多態,在編碼時,並不能確定調用的是哪一個繼承級別的方法實現,這個留在運行時解決,帶來的好處是代碼有更好的抽象度。
順便提一下,以不同參數,同樣方法名的重載,和Override(重寫/覆蓋),是兩個事情,不要弄混。

2. 什麼是多態性,使用多態有什麼好處

什麼是多態?

可以這么回答:

使用多態有什麼好處?

多態在代碼中的體現:

輸出結果:
貓吃魚
貓吃魚(因為描述的是真正的是一隻貓)

拓展:

多態性:同一操作作用於不同的對象,可以用不同的解釋,產生不同的執行結果,這就是多態性。

多態性通過派生類覆寫基類中的虛函數的方法來實現。

多態性分為兩種,一種是編譯時的多態性,一種是運行時的多態性。

編譯時的多態性:編譯時多態是通過重載來實現的。對於非虛的成員來說,系統在編譯時,根據傳遞的參數,返回的類型等信息決定實現何種操作。

運行時的多態性:運行時的多態性就是指直到系統運行時,才根據實際情況決定實現何種操作。

3. 面向對象的多態詳解 !!

面向對象的軟體開發語言具有三個重要的特點分別為封裝性、繼承性、多態性。封裝性即意味著對象封裝其內部的數據,使其對外不可見,以保證數據的安全性。繼承性是代碼復用的一個很好的解決方案,但是繼承關系是編譯器在編譯階段就為所有的對象決定的,因而在軟體工程過程中,繼承性太過死板,存在很大的局限性。而多態性,它是將多種不同的特殊行為進行抽象的一種能力,通過結合繼承性,多態性很好地解決了OO遇到的很多麻煩,使得面向對象的編程方式最終得到淋漓盡致的推廣。

多態性和泛型編程

各種編程語言都內置了多種基本數據結構並且支持自定義數據類型,因而程序員在程序設計過程中可能會遇到多種數據類型,而針對這些數據類型的邏輯操作很有可能是雷同的。此時為每一種數據類型都設計出相應的邏輯函數似乎已經變得很不現實,因而泛型編程孕育而生了。泛型編程的出現,可以說在軟體工程領域里是一個極大的進步。利用泛型編程,我們可以不為特定的類型進行專門編碼,而採用對不同類型進行通用編碼的方式來解決應對大量數據類型的問題。C++
STL是泛型編程的成功案例。利用Template函數,STL成功實現了對多種數據類型進行泛化的效果。而OO通過介面或者抽象類進一步實現了對類的泛化,也就是在面向對象過程中出現的新名詞—多態!

多態性特點

簡單來說,多態是具有表現多種形態的能力的特徵,在OO中是指,語言具有根據對象的類型以不同方式處理,即指同樣的消息被不同類型的對象接收時導致完全不同的行為,是對類的特定成員函數的再抽象。多態性在不同的編程語言中擁有不同的解決方案,但多態性的最終目標卻始終不變,都是「以不變應萬變」。

兩種多態方式

一般來說,多態主要是存在兩種類型:編譯時的多態和運行時的多態。

1
編譯時的多態主要是通過函數重載來實現的。所謂函數重載是指保持函數名不變,主要通過更改函數形參的個數以及形參的類型來定義出多個同名函數來實現對多種類型數據的邏輯處理。這種類型的多態關系是編譯器在編譯階段就已經在函數調用的地方確定的,因而運行過程中速度較快,但功能比較局限。

2
運行時的多態在不同的語言中擁有不同的實現方案。C++通過虛函數的晚捆綁來實現,而Java通過面向介面編程和面向抽象編程來實現動態調用相應的函數實現。但歸根結點,這些語言都是通過將多種特殊實現的類抽象為一個泛化類來實現運行多態。

面向介面編程

軟體工程中程序涉及到的對象越多,對象之間相似的概率越大,因而這時候抽象變成了可能。通過定義介面,程序設計者可以成功實現對方法的定義和實現的分離,因而應用程序不必考慮子類成員函數中是如何實現內部邏輯細節,只需知道該類對象向外公開的介面便可成功操縱這類對象。而這種編程方式,為以後程序的改動以及程序的健壯性和擴展性都提供了一個比較理想的解決方案。因此面向抽象編程已經成為OO界強烈推崇的編程方式。

OO思想已經深入廣大編程人員的工作中,如何能夠充分合理利用OO的特點達到最優化軟體體系結構將會成為每一個OO程序員應該思考的問題,相信OO思想能夠為大家的軟體設計帶來前所未有的效果。

4. java中多態性什麼意思

多態性:顧名思義就是擁有「多種形態」的含義,是指屬性或方法在子類中表現為多種形態。

在JAVA中有兩種多態是指:運行時多態和編譯時多態。多態性是面向對象的核心特徵之一,類的多態性提供類中成員設計的靈活性和方法執行的多樣性。

多態指允許不同類的對象對同一消息做出響應。即同一消息可以根據發送對象的不同而採用多種不同的行為方式。(發送消息就是函數調用)

實現多態的技術稱為:動態綁定(dynamic binding),是指在執行期間判斷所引用對象的實際類型,根據其實際的類型調用其相應的方法。

展資料:

多態的好處:

1、可替換性(substitutability)多態對已存在代碼具有可替換性。例如,多態對圓Circle類工作,對其他任何圓形幾何體,如圓環,也同樣工作。

2、可擴充性(extensibility)多態對代碼具有可擴充性。增加新的子類不影響已存在類的多態性、繼承性,以及其他特性的運行和操作。實際上新加子類更容易獲得多態功能。

3、介面性(interface-ability)多態是超類通過方法簽名,向子類提供了一個共同介面,由子類來完善或者覆蓋它而實現的。

4、靈活性(flexibility)它在應用中體現了靈活多樣的操作,提高了使用效率。

5、簡化性(simplicity)多態簡化對應用軟體的代碼編寫和修改過程,尤其在處理大量對象的運算和操作時,這個特點尤為突出和重要。

5. 編譯時的多態性和運行時的多態性在實現方法上有何不同

我不知道你哪本書上看到的,但是,只要不是後綁定就不能稱為多態,前綁定只能稱為代碼重用,比如函數的重載、覆蓋以及一般的類繼承。
多態的關鍵特點就是:在運行時虛基類指針指向派生類對象地址,而將派生類對象地址賦值給基類指針,這就是所謂的後綁定,編譯時綁定稱為前綁定,因此多態另一個特點就是「動態「。換句話說,如果是後綁定,編譯器事先是不知道在運行時指針將指向哪一種派生類的對象,因此基類指針必須是「虛「的,虛基類中不能有任何實現只有定義,此時虛基類的作用就是一個類介面,這樣才能在編譯時「模糊」掉類型匹配原則,基類的作用只是個約定,定義了函數調用格式,而只在運行時才確定指針具體指向哪一個對象。
而所謂編譯時的多態性根本不存在,如果編譯器能確定基類指針指向哪一個派生類對象地址,就不是多態,哪怕你採用重載覆蓋或者繼承,這些編譯器已經可以預知的事情,一旦編譯完成就固定了,運行時無法更改的,比如你不能在不重新編譯的情況下增加一個重載,這就制約了程序運行時的靈活性以及可擴充性。而多態完全可以實現「熱「更新,更多的是便於程序的可擴充性。你完全可以將派生類編譯在DLL中,每當更新程序時,只要替換掉DLL而不用重新編譯全部代碼。

6. JAVA中使用多態有的好處。有什麼用處

多態有編譯時多態 和運行時多態。
第一個是通過方法重載實現;第二個是通過方法覆蓋實現(子類覆蓋父類方法)。
第一種就是我們調用方法是不用區分參數類型,程序會自動執行相應方法,如: 加法運算,可以使int相加,可以是double相加,都是同一個方法名。
第二種就是動態綁定,使用父類引用指向子類對象,再調用某一父類中的方法時,不同子類會表現出不同結果。 這樣的作用就是擴展性極好,玩過網游的話應該知道 游戲中有不同的角色,它們都有一個父類,它們做相同動作時表現出來的效果就會不一樣,比如跑,魔法師的跑跟戰士的跑就不會一樣,這就是倆者都覆蓋了父類中的跑方法,各自有自己的現實,表現出來多態。 如果有一天你想再加個角色,只用再寫一個類繼承該父類,覆蓋其中的跑方法就行了,其他代碼不用怎麼改,所以可維護性也很好。

7. 談談你對Java中的多態的理解.(為什麼要使用多態,有什麼好處,一般用在什麼場合)

面向對象編程有三大特性:封裝、繼承、多態。

封裝隱藏了類的內部實現機制,可以在不影響使用的情況下改變類的內部結構,同時也保護了數據。對外界而已它的內部細節是隱藏的,暴露給外界的只是它的訪問方法。

繼承是為了重用父類代碼。兩個類若存在IS-A的關系就可以使用繼承。,同時繼承也為實現多態做了鋪墊。

那麼什麼是多態呢?多態的實現機制又是什麼?請看我一一為你揭開:

所謂多態

就是指程序中定義的引用變數所指向的具體類型和通過該引用變數發出的方法調用在編程時並不確定,而是在程序運行期間才確定,即一個引用變數倒底會指向哪個類的實例對象,該引用變數發出的方法調用到底是哪個類中實現的方法,必須在由程序運行期間才能決定。因為在程序運行時才確定具體的類,這樣,不用修改源程序代碼,就可以讓引用變數綁定到各種不同的類實現上,從而導致該引用調用的具體方法隨之改變,即不修改程序代碼就可以改變程序運行時所綁定的具體代碼,讓程序可以選擇多個運行狀態,這就是多態性。



比如你是一個酒神,對酒情有獨鍾。某日回家發現桌上有幾個杯子裡面都裝了白酒,從外面看我們是不可能知道這是些什麼酒,只有喝了之後才能夠猜出來是何種酒。你一喝,這是劍南春、再喝這是五糧液、再喝這是酒鬼酒….在這里我們可以描述成如下:

酒 a = 劍南春

酒 b = 五糧液

酒 c = 酒鬼酒

這里所表現的的就是多態。劍南春、五糧液、酒鬼酒都是酒的子類,我們只是通過酒這一個父類就能夠引用不同的子類,這就是多態——我們只有在運行的時候才會知道引用變數所指向的具體實例對象。

誠然,要理解多態我們就必須要明白什麼是「向上轉型」。在繼承中我們簡單介紹了向上轉型,這里就在啰嗦下:在上面的喝酒例子中,酒(Win)是父類,劍南春(JNC)、五糧液(WLY)、酒鬼酒(JGJ)是子類。我們定義如下代碼:

JNC a = new JNC();

對於這個代碼我們非常容易理解無非就是實例化了一個劍南春的對象嘛!但是這樣呢?

Wine a = new JNC();


在這里我們這樣理解,這里定義了一個Wine 類型的a,它指向JNC對象實例。由於JNC是繼承與Wine,所以JNC可以自動向上轉型為Wine,所以a是可以指向JNC實例對象的。這樣做存在一個非常大的好處,在繼承中我們知道子類是父類的擴展,它可以提供比父類更加強大的功能,如果我們定義了一個指向子類的父類引用類型,那麼它除了能夠引用父類的共性外,還可以使用子類強大的功能。


但是向上轉型存在一些缺憾,那就是它必定會導致一些方法和屬性的丟失,而導致我們不能夠獲取它們。所以父類類型的引用可以調用父類中定義的所有屬性和方法,對於只存在與子類中的方法和屬性它就望塵莫及了。



publicclassWine{
publicvoidfun1(){
System.out.println("Wine的Fun.....");
fun2();
}

publicvoidfun2(){
System.out.println("Wine的Fun2...");
}
}

publicclassJNCextendsWine{
/**
*@desc子類重載父類方法
*父類中不存在該方法,向上轉型後,父類是不能引用該方法的
*@parama
*@returnvoid
*/
publicvoidfun1(Stringa){
System.out.println("JNC的Fun1...");
fun2();
}

/**
*子類重寫父類方法
*指向子類的父類引用調用fun2時,必定是調用該方法
*/
publicvoidfun2(){
System.out.println("JNC的Fun2...");
}
}

publicclassTest{
publicstaticvoidmain(String[]args){
Winea=newJNC();
a.fun1();
}
}

-------------------------------------------------

Output:

Wine的Fun.....

JNC的Fun2...


從程序的運行結果中我們發現,a.fun1()首先是運行父類Wine中的fun1().然後再運行子類JNC中的fun2()。

分析:在這個程序中子類JNC重載了父類Wine的方法fun1(),重寫fun2(),而且重載後的fun1(String a)與 fun1()不是同一個方法,由於父類中沒有該方法,向上轉型後會丟失該方法,所以執行JNC的Wine類型引用是不能引用fun1(String a)方法。而子類JNC重寫了fun2() ,那麼指向JNC的Wine引用會調用JNC中fun2()方法。

所以對於多態我們可以總結如下:

指向子類的父類引用由於向上轉型了,它只能訪問父類中擁有的方法和屬性,而對於子類中存在而父類中不存在的方法,該引用是不能使用的,盡管是重載該方法。若子類重寫了父類中的某些方法,在調用該些方法的時候,必定是使用子類中定義的這些方法(動態連接、動態調用)。

對於面向對象而已,多態分為編譯時多態和運行時多態。其中編輯時多態是靜態的,主要是指方法的重載,它是根據參數列表的不同來區分不同的函數,通過編輯之後會變成兩個不同的函數,在運行時談不上多態。而運行時多態是動態的,它是通過動態綁定來實現的,也就是我們所說的多態性。




多態的實現

2.1實現條件

在剛剛開始就提到了繼承在為多態的實現做了准備。子類Child繼承父類Father,我們可以編寫一個指向子類的父類類型引用,該引用既可以處理父類Father對象,也可以處理子類Child對象,當相同的消息發送給子類或者父類對象時,該對象就會根據自己所屬的引用而執行不同的行為,這就是多態。即多態性就是相同的消息使得不同的類做出不同的響應。

Java實現多態有三個必要條件:繼承、重寫、向上轉型。

繼承:在多態中必須存在有繼承關系的子類和父類。

重寫:子類對父類中某些方法進行重新定義,在調用這些方法時就會調用子類的方法。

向上轉型:在多態中需要將子類的引用賦給父類對象,只有這樣該引用才能夠具備技能調用父類的方法和子類的方法。

只有滿足了上述三個條件,我們才能夠在同一個繼承結構中使用統一的邏輯實現代碼處理不同的對象,從而達到執行不同的行為。

對於Java而言,它多態的實現機制遵循一個原則:當超類對象引用變數引用子類對象時,被引用對象的類型而不是引用變數的類型決定了調用誰的成員方法,但是這個被調用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。


2.2實現形式

在Java中有兩種形式可以實現多態。繼承和介面。

2.2.1、基於繼承實現的多態

基於繼承的實現機制主要表現在父類和繼承該父類的一個或多個子類對某些方法的重寫,多個子類對同一方法的重寫可以表現出不同的行為。

publicclassWine{
privateStringname;

publicStringgetName(){
returnname;
}

publicvoidsetName(Stringname){
this.name=name;
}

publicWine(){
}

publicStringdrink(){
return"喝的是"+getName();
}

/**
*重寫toString()
*/
publicStringtoString(){
returnnull;
}
}

publicclassJNCextendsWine{
publicJNC(){
setName("JNC");
}

/**
*重寫父類方法,實現多態
*/
publicStringdrink(){
return"喝的是"+getName();
}

/**
*重寫toString()
*/
publicStringtoString(){
return"Wine:"+getName();
}
}

publicclassJGJextendsWine{
publicJGJ(){
setName("JGJ");
}

/**
*重寫父類方法,實現多態
*/
publicStringdrink(){
return"喝的是"+getName();
}

/**
*重寫toString()
*/
publicStringtoString(){
return"Wine:"+getName();
}
}

publicclassTest{
publicstaticvoidmain(String[]args){
//定義父類數組
Wine[]wines=newWine[2];
//定義兩個子類
JNCjnc=newJNC();
JGJjgj=newJGJ();

//父類引用子類對象
wines[0]=jnc;
wines[1]=jgj;

for(inti=0;i<2;i++){
System.out.println(wines[i].toString()+"--"+wines[i].drink());
}
System.out.println("-------------------------------");

}
}

OUTPUT:

Wine:JNC--喝的是JNC

Wine:JGJ--喝的是JGJ



在上面的代碼中JNC、JGJ繼承Wine,並且重寫了drink()、toString()方法,程序運行結果是調用子類中方法,輸出JNC、JGJ的名稱,這就是多態的表現。不同的對象可以執行相同的行為,但是他們都需要通過自己的實現方式來執行,這就要得益於向上轉型了。

我們都知道所有的類都繼承自超類Object,toString()方法也是Object中方法,當我們這樣寫時:



Objecto=newJGJ();

System.out.println(o.toString());


輸出的結果是Wine : JGJ。

Object、Wine、JGJ三者繼承鏈關系是:JGJ—>Wine—>Object。所以我們可以這樣說:當子類重寫父類的方法被調用時,只有對象繼承鏈中的最末端的方法才會被調用。但是注意如果這樣寫:


Objecto=newWine();

System.out.println(o.toString());

輸出的結果應該是Null,因為JGJ並不存在於該對象繼承鏈中。

所以基於繼承實現的多態可以總結如下:對於引用子類的父類類型,在處理該引用時,它適用於繼承該父類的所有子類,子類對象的不同,對方法的實現也就不同,執行相同動作產生的行為也就不同。

如果父類是抽象類,那麼子類必須要實現父類中所有的抽象方法,這樣該父類所有的子類一定存在統一的對外介面,但其內部的具體實現可以各異。這樣我們就可以使用頂層類提供的統一介面來處理該層次的方法。




2.2.2、基於介面實現的多態

繼承是通過重寫父類的同一方法的幾個不同子類來體現的,那麼就可就是通過實現介面並覆蓋介面中同一方法的幾不同的類體現的。

在介面的多態中,指向介面的引用必須是指定這實現了該介面的一個類的實常式序,在運行時,根據對象引用的實際類型來執行對應的方法。

繼承都是單繼承,只能為一組相關的類提供一致的服務介面。但是介面可以是多繼承多實現,它能夠利用一組相關或者不相關的介面進行組合與擴充,能夠對外提供一致的服務介面。所以它相對於繼承來說有更好的靈活性。

8. 請問一下Java里編譯時多態和運行時多態的區別,最好舉個例,謝謝

個人看法
多態的概念 父類引用指向子類對象 而實際調用的方法為子類的方法。
編譯時多態 Java里叫重載 嚴格來說不叫多態 運行時多態 有繼承 有重寫 父類引用指向子類對象
例子我看就算了 書上多 的是

9. 關於Java的編譯時多態和運行時多態

您想的有點復雜化了,簡單的說吧,您說的運行時的多態是分為可執行文件和非可執行文件,也就是說您的程序打沒打包,而您說的編譯時的多態也分為兩種;1、重載。2、繼承。前者是靜態的多態形式也就是說不可以用於多個類;針對方法,後者是可以在多個類之間使用,要記得只可以子類繼承父類,不可『以下犯上』。就像是java中的類型,一個是private,另一個是public。

閱讀全文

與編譯期多態和運行期多態的優缺點相關的資料

熱點內容
馬丁靴補色解壓 瀏覽:565
在設置app上怎麼找到個人熱點 瀏覽:752
按照檔案號生成文件夾 瀏覽:1000
程序員轉方向 瀏覽:109
lol敏捷加密 瀏覽:880
傳統公司眼中的加密貨幣 瀏覽:428
電腦圖標又出現文件夾怎麼去掉 瀏覽:962
排序演算法c和a 瀏覽:418
手機拍照上傳android 瀏覽:343
linux壓縮率 瀏覽:614
電腦瀏覽器加密埠 瀏覽:536
單片機線性電源 瀏覽:268
韓國雲伺服器評測 瀏覽:740
python輸出hello 瀏覽:593
如何在最左側添加文件夾 瀏覽:500
python實現https請求 瀏覽:472
一端無支座端梁要加密嗎 瀏覽:247
雲伺服器能做什麼兼職 瀏覽:972
大疆程序員姜 瀏覽:415
飢荒如何掛伺服器 瀏覽:244