摘要:同時(shí)繼承允許將對(duì)象視為它本身的類型或者它的父類型進(jìn)行處理,這是使用繼承設(shè)計(jì)多態(tài)的基礎(chǔ)。水果青蘋果設(shè)置名字為設(shè)置名字為香蕉橙子那么就是的多態(tài)表現(xiàn)。
面向?qū)ο缶幊逃腥筇匦裕悍庋b、繼承、多態(tài)。
封裝:將事物特征和行為抽象出來,并隱藏內(nèi)部具體的實(shí)現(xiàn)機(jī)制。隱藏即可以保護(hù)數(shù)據(jù)安全,也可以在不影響類的使用情況下對(duì)類進(jìn)行修改。對(duì)外界而言,暴露的僅僅是一個(gè)方法。
繼承:若兩個(gè)類之間是is-a的關(guān)系,就可以使用extends關(guān)鍵字對(duì)父類的代碼進(jìn)行復(fù)用。同時(shí)繼承允許將對(duì)象視為它本身的類型或者它的父類型進(jìn)行處理,這是使用繼承設(shè)計(jì)多態(tài)的基礎(chǔ)。
多態(tài):程序中定義的引用變量,它指向的具體類型和它的調(diào)用方法在編譯中并不確定,只有在程序運(yùn)行時(shí)才確定。這樣,不用修改程序代碼,就可以讓引用變量綁定不同的具體類型,使得調(diào)用的方法也隨之改變。
多態(tài)分成編譯時(shí)多態(tài)和運(yùn)行時(shí)多態(tài)。編譯時(shí)多態(tài)指的是方法的重載,屬于靜態(tài)多態(tài),當(dāng)編譯時(shí),會(huì)根據(jù)參數(shù)列表來區(qū)分不同的方法,編譯完成后,會(huì)生成不同的方法。而運(yùn)行時(shí)多態(tài)則為運(yùn)行時(shí)動(dòng)態(tài)綁定方法來實(shí)現(xiàn),指的就是多態(tài)性。
多態(tài)性
前置概念:
方法綁定:將一個(gè)方法的調(diào)用和方法主體關(guān)聯(lián)起來就叫做方法綁定。
從多態(tài)的概念上可以看出,在程序中,方法綁定并不一定發(fā)生在程序運(yùn)行期間,還有在程序運(yùn)行前就綁定的情況。在程序運(yùn)行前就綁定的稱作前期綁定,而在運(yùn)行時(shí)根據(jù)對(duì)象具體類型進(jìn)行綁定的稱作后期綁定或動(dòng)態(tài)綁定。實(shí)現(xiàn)后期綁定必須有某種機(jī)制以便在運(yùn)行時(shí)判斷對(duì)象的類型。
向上轉(zhuǎn)型:把一個(gè)對(duì)象的引用視為對(duì)它父類型的引用稱作向上轉(zhuǎn)型。缺陷:在使用過程中,只能以父類為基準(zhǔn),使用也只能使用父類中的屬性方法,導(dǎo)致丟失子類的一部分屬性和方法。
例如:蘋果,香蕉,橙子都是水果,實(shí)體類Apple,Banana,Orange全都繼承Fruit類。
public class Fruit { public void name(){ System.out.println("水果"); } public static void main(String[] arg0){ Fruit apple = new Apple(); apple.name(); } } class Apple extends Fruit{ public void name(){ System.out.println("青蘋果"); } public void name(String name){ System.out.println("設(shè)置名字為"+name); } public void setName(String color){ System.out.println("設(shè)置名字為"+name); } } class Banana extends Fruit{ public void name(){ System.out.println("香蕉"); } } class Orange extends Fruit{ public void name(){ System.out.println("橙子"); } }
那么
Fruit apple = new Apple(); Fruit banana = new Banana(); Fruit orange = new Orange();
就是Fruit的多態(tài)表現(xiàn)。可以理解成引用變量apple類型為Fruit,具體指向的則是Apple對(duì)象的實(shí)例,具體理解為:Apple對(duì)象繼承Fruit,所以Apple會(huì)自動(dòng)的向上轉(zhuǎn)型為Fruit對(duì)象,所以apple可以指向Apple。但是由于使用了向上轉(zhuǎn)型,那么也會(huì)存在向上轉(zhuǎn)型的缺陷。例如:apple是不能使用name(String color)和setName(String name)方法的,不管是子類的屬性還是子類特有的方法,包括子類重載的方法。例如apple.name();可以得到值:青蘋果。但是,編寫apple.name("紅蘋果")或者apple.setName("紅蘋果")是會(huì)提示錯(cuò)誤。
多態(tài)的實(shí)現(xiàn):
1.用繼承設(shè)計(jì)進(jìn)行設(shè)計(jì)
條件:繼承關(guān)系、重寫父類中的方法和隱式的向上轉(zhuǎn)型。
在之前的代碼,添加一個(gè)實(shí)體類Person,內(nèi)部存在行為eat(Fruit fruit)方法。
class Person{ public void eat(Fruit fruit){ System.out.print("吃的"); fruit.name(); } } public static void main(String[] arg0){ Fruit apple = new Apple(); Fruit banana = new Banana(); Fruit orange = new Orange(); Person july = new Person(); july.eat(apple); july.eat(banana); july.eat(orange); } 輸出: 吃的青蘋果 吃的香蕉 吃的橙子
可以看到并沒有使用eat(Apple apple)一類的方法,但也能正確的執(zhí)行方法,我們不用為多帶帶的每個(gè)人創(chuàng)建類似于eatApple(Apple apple)這樣的方法,而且對(duì)于每一個(gè)繼承了Fruit類的水果類來說,都可以直接給person.eat(Fruit)調(diào)用。
2.用接口進(jìn)行設(shè)計(jì)
條件:實(shí)現(xiàn)接口,并覆蓋其中的方法。
類似于使用繼承設(shè)計(jì)多態(tài),接口設(shè)計(jì)如下所示:
public class FruitDemo implements IFruit{ @Override public void name() { // TODO Auto-generated method stub System.out.println("水果"); } public static void main(String[] arg0){ AppleDemo apple = new AppleDemo(); BananaDemo banana = new BananaDemo(); PersonDemo july = new PersonDemo(); july.eat(apple); july.eat(banana); } } class PersonDemo{ public void eat(IFruit fruit){ System.out.print("吃的"); fruit.name(); } } class AppleDemo implements IFruit{ @Override public void name() { // TODO Auto-generated method stub System.out.println("蘋果"); } } class BananaDemo implements IFruit{ @Override public void name() { // TODO Auto-generated method stub System.out.println("香蕉"); } } interface IFruit{ void name(); } 輸出: 吃的蘋果 吃的香蕉
可以看到,程序中Person類實(shí)例july動(dòng)態(tài)調(diào)用實(shí)現(xiàn)了IFruit接口的類,并且正確返回了信息。
多態(tài)特性之協(xié)變返回類型
子類方法的返回類型可以是父類方法的返回類型的子類。例如:
public class Fruit { public String name = "水果"; public String getName(){ System.out.println("fruit name --"+ name); return name; } public static void main(String[] arg0){ Person person = new Person(); person.buy().getName(); Person man = new Man(); man.buy().getName(); } } class Apple extends Fruit{ public String name = "蘋果"; public String getName(){ System.out.println("apple name --"+ name); return name; } } class Person{ public Fruit buy(){ return new Fruit(); } } class Man extends Person{ public Apple buy(){ return new Apple(); } } 輸出: fruit name --水果 apple name --蘋果
在這里看到,子類Man中的方法,返回類型并不是Fruit,而是Fruit的子類,運(yùn)行的也是子類Apple的方法。
多態(tài)存在的缺陷:
1.對(duì)私有方法和final修飾的方法無效。
public class Fruit { public void name(){ System.out.println("水果"); } public final void findName(){ System.out.println("找水果"); } private void getName(){ System.out.println("拿水果"); } public static void main(String[] arg0){ Fruit apple = new Apple(); apple.findName(); apple.getName(); } } class Apple extends Fruit{ public void getName(){ System.out.println("拿到蘋果"); } public void name(){ System.out.println("青蘋果"); } public void name(String name){ System.out.println("蘋果設(shè)置成"+name); } public void setName(String name){ System.out.println("蘋果設(shè)置成"+name); } } 輸出: 找水果 拿水果
2.對(duì)父類字段和靜態(tài)方法無效。
public class Fruit { public String name = "水果"; public String getName(){ return name; } public static String getFruitName(){ return "水果"; } public static void main(String[] arg0){ Fruit apple = new Apple(); System.out.println("apple.name = "+apple.name+";apple.getName() = "+apple.getName()); Apple apple1 = new Apple(); System.out.println("apple1.name = "+apple1.name+";apple1.getName() = "+apple1.getName()+";apple1.getName1() = "+apple1.getName1()); System.out.println("Fruit.getFruitName = "+ Fruit.getFruitName()+";Apple.getFruitName = "+Apple.getFruitName()); } } class Apple extends Fruit{ public String name = "蘋果"; public String getName(){ return name; } public static String getFruitName(){ return "蘋果"; } public String getName1(){ return super.name; } } 輸出: apple.name = 水果;apple.getName() = 蘋果 apple1.name = 蘋果;apple1.getName() = 蘋果;apple1.getName1() = 水果 Fruit.getFruitName = 水果;Apple.getFruitName = 蘋果
可以看到 字段并不會(huì)覆蓋的,在子類Apple中是存在兩個(gè)name字段的,當(dāng)使用Fruit apple引用時(shí),apple.name使用的是父類Fruit中的字段,而當(dāng)Apple apple1時(shí),使用的是子類自己的字段。
靜態(tài)方法是不會(huì)有多態(tài)性的,它關(guān)聯(lián)的對(duì)象,而不是實(shí)例。
構(gòu)造函數(shù)和多態(tài):
構(gòu)造函數(shù)執(zhí)行的順序:
1.調(diào)用基類的構(gòu)造器,這個(gè)順序會(huì)不斷遞歸下去,因?yàn)闃?gòu)造一個(gè)類,先構(gòu)造基類,直到樹結(jié)構(gòu)的最頂層。
2.按聲明順序調(diào)用成員的初始化方法。
3.調(diào)用導(dǎo)出類的構(gòu)造器主體
構(gòu)造器內(nèi)部的多態(tài)方法:
如果一個(gè)構(gòu)造方法的內(nèi)部調(diào)用正在構(gòu)造的對(duì)象的一個(gè)動(dòng)態(tài)綁定方法,會(huì)發(fā)生什么情況?例如:
public class Fruit { public String name = "水果"; public Fruit(){ System.out.println("getName before--"); System.out.println("getName--"+getName()); System.out.println("getName after --"); } public String getName(){ return name; } public static void main(String[] arg0){ Fruit apple =new Apple(); } } class Apple extends Fruit{ public String name = "蘋果"; public Apple(){ System.out.println("Apple getName--"+getName()); } public String getName(){ return name; } } 輸出: getName before-- getName--null getName after -- Apple getName--蘋果
可以看到,在結(jié)果中存在一個(gè)null值,如果當(dāng)前屬性是基本數(shù)據(jù)類型,那么輸出的就是類型的初始默認(rèn)值。之后會(huì)按照聲明順序來構(gòu)造實(shí)例,所以后面得到的就是有值得了。
歡迎加入學(xué)習(xí)交流群569772982,大家一起學(xué)習(xí)交流。
。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/67670.html
摘要:寫這篇總結(jié),主要是記錄下自己的學(xué)習(xí)經(jīng)歷,算是自己對(duì)知識(shí)的一個(gè)回顧。這個(gè)階段學(xué)習(xí)的時(shí)候,要學(xué)會(huì)使用開發(fā)工具,比如或者來學(xué)習(xí)。這個(gè)階段需要自己對(duì)自己有很強(qiáng)的自律去學(xué)習(xí),不要看了一半就放棄了。 showImg(https://segmentfault.com/img/bVbaNtw?w=1232&h=822); 寫這篇總結(jié),主要是記錄下自己的學(xué)習(xí)經(jīng)歷,算是自己對(duì)知識(shí)的一個(gè)回顧。也給想要學(xué)習(xí) ...
摘要:寫這篇總結(jié),主要是記錄下自己的學(xué)習(xí)經(jīng)歷,算是自己對(duì)知識(shí)的一個(gè)回顧。這個(gè)階段學(xué)習(xí)的時(shí)候,要學(xué)會(huì)使用開發(fā)工具,比如或者來學(xué)習(xí)。這個(gè)階段需要自己對(duì)自己有很強(qiáng)的自律去學(xué)習(xí),不要看了一半就放棄了。 showImg(https://segmentfault.com/img/bVbaNtw?w=1232&h=822); 寫這篇總結(jié),主要是記錄下自己的學(xué)習(xí)經(jīng)歷,算是自己對(duì)知識(shí)的一個(gè)回顧。也給想要學(xué)習(xí) ...
摘要:寫這篇總結(jié),主要是記錄下自己的學(xué)習(xí)經(jīng)歷,算是自己對(duì)知識(shí)的一個(gè)回顧。這個(gè)階段學(xué)習(xí)的時(shí)候,要學(xué)會(huì)使用開發(fā)工具,比如或者來學(xué)習(xí)。這個(gè)階段需要自己對(duì)自己有很強(qiáng)的自律去學(xué)習(xí),不要看了一半就放棄了。 showImg(https://segmentfault.com/img/bVbaNtw?w=1232&h=822); 寫這篇總結(jié),主要是記錄下自己的學(xué)習(xí)經(jīng)歷,算是自己對(duì)知識(shí)的一個(gè)回顧。也給想要學(xué)習(xí) ...
閱讀 4093·2021-11-22 09:34
閱讀 1568·2021-11-04 16:10
閱讀 1796·2021-10-11 10:59
閱讀 3333·2019-08-30 15:44
閱讀 2104·2019-08-30 13:17
閱讀 3537·2019-08-30 11:05
閱讀 802·2019-08-29 14:02
閱讀 2673·2019-08-26 13:34