【騷全帶你學(xué)Java---十三、面向?qū)ο笾嚯摹?/h1>

多肽核心機(jī)制

1.面向?qū)ο笞詈诵牡臋C(jī)制——?jiǎng)討B(tài)綁定,也叫多態(tài)
2.多態(tài)就是指程序中定義的引用變量所指向的具體類型和通過(guò)該引用變量發(fā)出的方法調(diào)用在編譯時(shí)并不確定,而是在程序運(yùn)行期間才確定,即一個(gè)引用變量倒底會(huì)指向哪個(gè)類的實(shí)例對(duì)象,該引用變量發(fā)出的方法調(diào)用到底是哪個(gè)類中實(shí)現(xiàn)的方法,必須在由程序運(yùn)行期間才能決定。因?yàn)樵诔绦蜻\(yùn)行時(shí)才確定具體的類,這樣,不用修改源程序代碼,就可以讓引用變量綁定到各種不同的類實(shí)現(xiàn)上,從而導(dǎo)致該引用調(diào)用的具體方法隨之改變,即不修改程序代碼就可以改變程序運(yùn)行時(shí)所綁定的具體代碼,讓程序可以選擇多個(gè)運(yùn)行狀態(tài),這就是多態(tài)性。這個(gè)跟iOS中的運(yùn)行時(shí)runtime運(yùn)行時(shí)具有類似的原理。
3.指向子類的父類引用由于向上轉(zhuǎn)型了,它只能訪問(wèn)父類中擁有的方法和屬性,而對(duì)于子類中存在而父類中不存在的方法,該引用是不能使用的,盡管是重載該方法。若子類重寫(xiě)了父類中的某些方法,在調(diào)用該些方法的時(shí)候,必定是使用子類中定義的這些方法(動(dòng)態(tài)連接、動(dòng)態(tài)調(diào)用)
4.在繼承鏈中對(duì)象方法的調(diào)用存在一個(gè)優(yōu)先級(jí):this.Display(object)、super.Display(object)、this.Display((super)object)、super.Display((super)object)。

多肽的定義

指允許不同類的對(duì)象對(duì)同一消息做出響應(yīng)。即同一消息可以根據(jù)發(fā)送對(duì)象的不同而采用多種不同的行為方式。(發(fā)送消息就是函數(shù)調(diào)用)

多態(tài)存在的三個(gè)必要條件
  • 要有繼承;
  • 要有重寫(xiě);
  • 父類引用指向子類對(duì)象。

為什么要用多肽,好處是哪些?

我們都知道,一個(gè)事物的產(chǎn)生必然有其存在的道理,很多都是為了解決一些難題而產(chǎn)生,那么多肽具有哪些有點(diǎn)呢。

  • 1.可替換性(substitutability)。多態(tài)對(duì)已存在代碼具有可替換性。例如,多態(tài)對(duì)圓Circle類工作,對(duì)其他任何圓形幾何體,如圓環(huán),也同樣工作。
  • 2.可擴(kuò)充性(extensibility)。多態(tài)對(duì)代碼具有可擴(kuò)充性。增加新的子類不影響已存在類的多態(tài)性、繼承性,以及其他特性的運(yùn)行和操作。實(shí)際上新加子類更容易獲得多態(tài)功能。例如,在實(shí)現(xiàn)了圓錐、半圓錐以及半球體的多態(tài)基礎(chǔ)上,很容易增添球體類的多態(tài)性。
  • 3.接口性(interface-ability)。多態(tài)是超類通過(guò)方法簽名,向子類提供了一個(gè)共同接口,由子類來(lái)完善或者覆蓋它而實(shí)現(xiàn)的。如圖8.3所示。圖中超類Shape規(guī)定了兩個(gè)實(shí)現(xiàn)多態(tài)的接口方法,computeArea()以及computeVolume()。子類,如Circle和Sphere為了實(shí)現(xiàn)多態(tài),完善或者覆蓋這兩個(gè)接口方法。
  • 4.靈活性(flexibility)。它在應(yīng)用中體現(xiàn)了靈活多樣的操作,提高了使用效率。
  • 5.簡(jiǎn)化性(simplicity)。多態(tài)簡(jiǎn)化對(duì)應(yīng)用軟件的代碼編寫(xiě)和修改過(guò)程,尤其在處理大量對(duì)象的運(yùn)算和操作時(shí),這個(gè)特點(diǎn)尤為突出和重要。

代碼帶你認(rèn)識(shí)多肽

多態(tài)體現(xiàn)的格式:

父類類型 變量名 = new 子類對(duì)象;
變量名.方法名();

父類類型:指子類對(duì)象繼承的父類類型,或者實(shí)現(xiàn)的父接口

Fu f = new Zi();
f.method();
當(dāng)使用多態(tài)方式調(diào)用方法時(shí),首先檢查父類中是否有該方法,如果沒(méi)有,則編譯錯(cuò)誤;如果有,執(zhí)行的是子類重寫(xiě)后方法。
  • 代碼如下:
//定義父類
public abstract class Animal {
  public abstract void eat();
}
//定義子類
class Cat extends Animal {
  public void eat() {
  System.out.println("吃魚(yú)");
 }
}
class Dog extends Animal {
  public void eat() {
  System.out.println("吃骨頭");
 }
}
//定義測(cè)試類
public class Test {
public static void main(String[] args) {
// 多態(tài)形式,創(chuàng)建對(duì)象
  Animal a1 = new Cat();
// 調(diào)用的是 Cat 的 eat
  a1.eat();
// 多態(tài)形式,創(chuàng)建對(duì)象
   Animal a2 = new Dog();
// 調(diào)用的是 Dog 的 eat
   a2.eat();
 }
}

代碼告訴你多肽的好處

實(shí)際開(kāi)發(fā)的過(guò)程中,父類類型作為方法形式參數(shù),傳遞子類對(duì)象給方法,進(jìn)行方法的調(diào)用,更能體現(xiàn)出多態(tài)的擴(kuò)展 性與便利。代碼如下:

//定義父類
public abstract class Animal {
    public abstract void eat();
}
//定義子類
class Cat extends Animal {
   public void eat() {
   System.out.println("吃魚(yú)");
  }
}
class Dog extends Animal {
   public void eat() {
   System.out.println("吃骨頭");
  }
}
//定義測(cè)試類
public class Test {
public static void main(String[] args) {
// 多態(tài)形式,創(chuàng)建對(duì)象
Cat c = new Cat();
Dog d = new Dog();
// 調(diào)用showCatEat
showCatEat(c);
// 調(diào)用showDogEat
showDogEat(d);
/*
以上兩個(gè)方法, 均可以被showAnimalEat(Animal a)方法所替代
而執(zhí)行效果一致
*/
showAnimalEat(c);
showAnimalEat(d);
}
public static void showCatEat (Cat c){
c.eat();
}
public static void showDogEat (Dog d){
d.eat();
}
public static void showAnimalEat (Animal a){
a.eat();
}
}

由于多態(tài)特性的支持,showAnimalEat方法的Animal類型,是Cat和Dog的父類類型,父類類型接收子類對(duì)象,當(dāng)然可以把Cat對(duì)象和Dog對(duì)象,傳遞給方法。
當(dāng)eat方法執(zhí)行時(shí),多態(tài)規(guī)定,執(zhí)行的是子類重寫(xiě)的方法,那么效果自然與showCatEat、showDogEat方法一致,所以showAnimalEat完全可以替代以上兩方法。
不僅僅是替代,在擴(kuò)展性方面,無(wú)論之后再多的子類出現(xiàn),我們都不需要編寫(xiě)showXxxEat方法了,直接使用showAnimalEat都可以完成。
所以,多態(tài)的好處,體現(xiàn)在,可以使程序編寫(xiě)的更簡(jiǎn)單,并有良好的擴(kuò)展

引用類型轉(zhuǎn)換

多態(tài)的轉(zhuǎn)型分為向上轉(zhuǎn)型與向下轉(zhuǎn)型兩種:

向上轉(zhuǎn)型

  • 向上轉(zhuǎn)型:多態(tài)本身是子類類型向父類類型向上轉(zhuǎn)換的過(guò)程,這個(gè)過(guò)程是默認(rèn)的。
    當(dāng)父類引用指向一個(gè)子類對(duì)象時(shí),便是向上轉(zhuǎn)型。
    使用格式:

父類類型 變量名 = new 子類類型();
如:Animal a = new Cat();

向下轉(zhuǎn)型

  • 向下轉(zhuǎn)型:父類類型向子類類型向下轉(zhuǎn)換的過(guò)程,這個(gè)過(guò)程是強(qiáng)制的
    一個(gè)已經(jīng)向上轉(zhuǎn)型的子類對(duì)象,將父類引用轉(zhuǎn)為子類引用,可以使用強(qiáng)制類型轉(zhuǎn)換的格式,便是向下轉(zhuǎn)型。
    使用格式:

子類類型 變量名 = (子類類型) 父類變量名;
如:Cat c =(Cat) a;

為什么要轉(zhuǎn)型

當(dāng)使用多態(tài)方式調(diào)用方法時(shí),首先檢查父類中是否有該方法,如果沒(méi)有,則編譯錯(cuò)誤。也就是說(shuō),不能調(diào)用子類擁
有,而父類沒(méi)有的方法。編譯都錯(cuò)誤,更別說(shuō)運(yùn)行了。這也是多態(tài)給我們帶來(lái)的一點(diǎn)"小麻煩"。所以,想要調(diào)用子
類特有的方法,必須做向下轉(zhuǎn)型。

  • 轉(zhuǎn)型演示,代碼如下:
//定義類
abstract class Animal {
  abstract void eat();
}
class Cat extends Animal {
  public void eat() {
  System.out.println("吃魚(yú)");
}
public void catchMouse() {
  System.out.println("抓老鼠");
 }
}
class Dog extends Animal {
  public void eat() {
  System.out.println("吃骨頭");
 }
public void watchHouse() {
  System.out.println("看家");
 }
}

//定義測(cè)試類
public class Test {
  public static void main(String[] args) {
  // 向上轉(zhuǎn)型
  Animal a = new Cat();
  a.eat(); // 調(diào)用的是 Cat 的 eat
  // 向下轉(zhuǎn)型
  Cat c = (Cat)a;
  c.catchMouse(); // 調(diào)用的是 Cat 的 catchMouse
 }
}

轉(zhuǎn)型的異常

轉(zhuǎn)型的過(guò)程中,一不小心就會(huì)遇到這樣的問(wèn)題,請(qǐng)看如下代碼:

public class Test {
   public static void main(String[] args) {
   // 向上轉(zhuǎn)型
  Animal a = new Cat();
  a.eat(); // 調(diào)用的是 Cat 的 eat
  // 向下轉(zhuǎn)型
  Dog d = (Dog)a;
  d.watchHouse(); // 調(diào)用的是 Dog 的 watchHouse 【運(yùn)行報(bào)錯(cuò)】
 }
}

這段代碼可以通過(guò)編譯,但是運(yùn)行時(shí),卻報(bào)出了 ClassCastException ,類型轉(zhuǎn)換異常!這是因?yàn)椋髅鲃?chuàng)建了Cat類型對(duì)象,運(yùn)行時(shí),當(dāng)然不能轉(zhuǎn)換成Dog對(duì)象的。這兩個(gè)類型并沒(méi)有任何繼承關(guān)系,不符合類型轉(zhuǎn)換的定義。為了避免ClassCastException的發(fā)生,Java提供了 instanceof 關(guān)鍵字,給引用變量做類型的校驗(yàn),格式如下:

變量名 instanceof 數(shù)據(jù)類型
如果變量屬于該數(shù)據(jù)類型,返回true。
如果變量不屬于該數(shù)據(jù)類型,返回false。

所以,轉(zhuǎn)換前,我們最好先做一個(gè)判斷,代碼如下:

public class Test {
   public static void main(String[] args) {
   // 向上轉(zhuǎn)型
    Animal a = new Cat();
    a.eat(); // 調(diào)用的是 Cat 的 eat
    // 向下轉(zhuǎn)型
    if (a instanceof Cat){
      Cat c = (Cat)a;
      c.catchMouse(); // 調(diào)用的是 Cat 的 catchMouse
   } else if (a instanceof Dog){
     Dog d = (Dog)a;
     d.watchHouse(); // 調(diào)用的是 Dog 的 watchHouse
    }
 }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,443評(píng)論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,530評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,407評(píng)論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,981評(píng)論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,759評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,204評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,263評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,415評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,955評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,782評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,983評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,222評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,650評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,892評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,675評(píng)論 3 392
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,967評(píng)論 2 374

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