多態相對于封裝和繼承這兩個名詞就不是那么生活化了。這個詞最早是一個生物的專業用詞,它的指的是同一個物種在不同的環境當中可能出現的多樣化表現。那么衍生到了面向對象編程中,它的含義呢,我們用一句經典來話來描述:相同的行為,不同的實現。
成都創新互聯公司是一家專注于網站設計制作、成都網站建設與策劃設計,藤縣網站建設哪家好?成都創新互聯公司做網站,專注于網站建設十載,網設計領域的專業建站公司;建站業務涵蓋:藤縣等地區。藤縣做網站價格咨詢:189820811081、多態指的是行為的多樣性,沒有屬性多態這一說;
2、相同的行為指的是同名方法,也就是說方法名相同,我們就認為這是相同的行為。 由此,我們前面學習的方法重載和方法重寫其實都是多態的表現。
最近面試看到的:屬性能不能重寫?1、首先這個說法不專業,重寫特指的是方法,但是它要描述的意思其實我們懂,那就是父類中定義了一個屬性,子類能不能再定義一個同名屬性把它給覆蓋掉;
2、在語法上,這是可以的,不會報錯。但是子類定義的屬性是不會把父類定義的屬性給覆蓋掉;而是兩個屬性同時存在于對象身上,父類定義的存在于子類對象的父類對象部分(上半截),子類定義的存在于子類對象的子類特有部分(下半截)。那么,如何區分呢?用this.訪問子類定義的該屬性;用super.訪問父類定義的該屬性。
3、在實際場景中,這種設計是沒有意義的。因為父類定義了一個屬性,子類通過繼承自動擁有了這個屬性,那么子類再去定義一個一摸一樣的屬性是沒有任何意義的,屬于重復勞動。這是屬于子類的設計人員沒有理解父類設計的意圖。
多態的意義封裝是面向對象的基礎; 繼承是在封裝的基礎上,實現代碼的復用性; 多態考量的是代碼的豐富度。
多態分為兩種: 1、靜態多態;2、動態多態。
這里的靜態和我們前面學習的static關鍵字沒有關系,它描述的是:在編譯期既能確定某個多態方法的具體執行效果; 這里的動態多態是指在運行期,根據綁定對象的不同,才能確定多態方法執行的效果。
我們在前面學過的方法的重載和方法的重寫都是屬于靜態多態。靜態多態雖然有豐富度的體現,但是是不夠的,因為它在編譯期就把執行效果固定下來了。而我們以后用得更多的是動態多態。
動態多態是由兩個技術合并使用才有的效果:動態綁定技術 + 方法的重寫。
動態綁定技術首先我們從現象上來看一個效果: 本類引用 指向 本類對象; 父類引用 指向 子類對象;
在Java當中只有這兩種情況,也就是說賦值符號左右兩端如果類型不一致,那么只有后面這種情況。
從內存上解釋為什么父類引用可以指向子類對象呢? 既然是父子關系,還是在做繼承,那么還是跟內存疊加有關系。每一個子類對象的上半截都是一個完整的父類對象部分,當父類引用指過去的時候,是能夠看到完整的父類對象信息的。
沒有繼承關系的類,不能保證A類引用指到B類對象,能看到B類對象中有A類定義的內容,所以不允許!
子類引用指向父類對象的時候,父類對象里面沒有子類特有部分,所以缺失了內容,也不允許!
從場景上解釋一個對象屬于子類,一定也屬于它的父類。子和父是is-a關系,這是說得通的。
但是一個對象屬于父類,你能保證它一定屬于子類嗎?
而沒有繼承關系的,那就更說不通的了,比如:指鹿為馬。 明明是一個鹿的對象,你偏要用馬的引用去指向它,肯定是不對的。你可以說它是動物、可以說它是寵物、因為鹿is-a動物;鹿 is-a 寵物;都是可行的,但鹿 is not a 馬。
動態體現在哪兒?如果我們手上現在擁有一個父類引用,那么我們就不能確定這個引用到底是指向哪一個具體的對象的了。
它既可能指向自己類型的對象,也可能指向自己的各種子類對象。而自己的某個方法,是可以被子類重寫成不同的實現效果的。那么用這個引用執行重寫方法,也就不能確定到底重寫前還是重寫后,是A子類重寫后,還是其它子類重寫后的效果了。只有等程序運行起來以后,根據該引用具體綁定的對象到底是誰,才能夠運行出具體的效果。--- 這就是動態的體現。
語法細節轉型技術
賦值符號左右兩端數據類型不一致,就會發生數據類型轉換。 父類引用 = 子類對象 也是兩端數據類型不一致,所以也屬于轉型技術。
我們用我們前面學習的基本數據類型轉型技術去推衍現在的引用數據類型的轉型技術。
基本數據類型轉型技術
1、前提:不是所有基本數據類型之間都能夠進行轉型,boolean不參與的;
2、自動類型轉換 小類型值 賦值給 大類型的變量強調:這里的大小 是 數據類型能表示的范圍的大小,而不是空間的大小。
int num = 'A'; float f = num; double d = 100;
效果:不需要使用任何特殊語法,直接完成類型轉換并且賦值成功。
3、強制類型轉換 大類型的值 賦值給 小類型的變量
效果: 3-1、直接書寫后,編譯報錯; 3-2、使用(目標類型)的強轉語法,編譯才能夠通過; 3-3、運行的效果是有風險性的,精度有可能丟失。
引用數據類型轉型技術
1、前提:不是所有引用數據類型之間都能夠做轉型,只有有繼承關系的類型之間才可以;
2、自動類型轉換 子類對象 賦值給 父類引用 子類表示的范圍 是小于 父類表示的范圍,所以仍然是把小的數據值交給大的變量。與基本數據類型的自動轉換要求是一摸一樣的。
只是說它有另一個特殊的名字,又叫做“向上轉型”而已。因為在繼承樹上,父類在上,子類在下;
效果:不需要使用任何特殊語法,直接完成類型轉換并且賦值成功。
3、強制類型轉換 大類型的值 賦值給 小類型的引用
又被稱為"向下轉型".
效果: 1、直接書寫后,編譯報錯; 2、使用(目標類型)的強轉語法,編譯才能夠通過; 3、運行的效果是有風險性的,風險性是運行時報錯(ClassCastException),中斷程序的執行。
對風險性探討:1、我們發現并不是每次強轉都一定成功,那么情況時如何的呢? 要想強轉以后,編譯通過且運行也通過,只有一種情況,那就是:最終的內存結果只能是本類引用指向本類對象。
2、強轉語法只是在編譯期進行一個強制性的語法說明,說明什么呢?告訴編譯器,我這個父類引用確實是指向的某種子類對象。
3、但是運行起來以后,如果滿足你的強制說明,那么沒有問題運行成功;如果不滿足你的強制說明,那么就會運行失敗,報出ClassCastException。
強調:強轉語法不是把A類對象變成B對象,只是在編譯期達成的一個口頭約束而已。
父類引用指向子類對象,我們能訪問什么呢?
1、父類引用只能看到子類對象從父類繼承而來的屬性和行為,當然要受訪問修飾符限制;注意:子類對象身上是有子類特有屬性和行為的,只是站在父類引用的角度上看不到而已。
2、要想看到,要把引用換成子類引用,這個時候要使用強轉語法,同時還必須保證運行起來以后真正給出的對象是符合強轉語法的。
3、特例是在父類中定義,被子類重寫的行為。由于這個行為是定義在父類中,所以父類引用能看到;而對象又是子類對象,所以執行的效果是子類重寫后的效果。
練習:書寫一個寵物類Pet,擁有一個叫的行為;書寫Pet的兩個子類Dog和Cat,分別實現叫的行為。再書寫一個主人類Master,擁有一個寵物對象,主人有一個行為是喂養feed,在該方法中調用自己寵物叫的行為。最后,在main方法中測試。
instanceof
在練習當中,我們看到在有的場景里面,確實會存在需要強轉的情況。但是,強轉又有風險度,所以,我們需要先判斷類型是否匹配,這就要用到instanceof了。
instanceof是一個關鍵字,也是一個運算符。它是專門用來判斷一個對象是否屬于某個類型的,運算后的結果是boolean型結果。
語法: 對象 instanceof 類型
instanceof是專門用來規避強轉帶來的ClassCastException風險的,類似于非空判斷專門用來解決NullPointerException風險的。
多態的應用多態參數
當我們在設計參數的時候,把參數的類型設計為父類類型,那么所有的子類對象都能夠通過這個參數,傳遞到這個方法里面去。
? public void cure(角色 r){ ? ? ?if(r instanceof 士兵){ ? ? ? }else if(.....){ ? ? ? } ? } ?
這樣的多態應用帶來了面向對象設計中非常重要的一個原則:開閉原則。
開閉原則:Software should be opened for extension, but closed for modification。
軟件對于擴展來說應該是開放的,對于修改來說應該是關閉。
也就是說好的軟件設計,應該能夠可以隨著業務的擴展去增加新的功能,但是不應該修改已有的功能。
多態集合
int[] array = new int[10];
Object[] arrayObj = new Object[10];
可以解決數組只能存放同一數據類型元素的問題。
補一下 switch的新語法 var關鍵字Java語言和JavaScript語言有一個很重要的區別: Java語言是強類型的編程語言;而JS是弱類型的。
int num = 10; String msg = "hello";
var num = 10; var name = "zhang3"; var pi = 3.14; ? num = "hello"; ?
在15年左右的時候,Java想去學習JS的這種聲明變量的簡便性,所以它也引入了var關鍵字來聲明變量。
但問題是,Java本身是強類型的,引入了以后又不能改變它的強類型本質,所以導致這個關鍵字不倫不類有很多限制。
1、必須要對var聲明的變量馬上賦值,因為編譯器是根據這個賦的值的類型才能判定這個變量是什么數據類型的;
2、一旦賦值成功后,這個變量的類型就被確定了,后面也不能更改,也不能存放其它類型的數據值;
3、var聲明的變量只能是局部變量,不能聲明為屬性的類型,也不能聲明為參數的類型。
4、所以在java中這個var變量的使用就沒有啥意義了。 唯一的意義可能僅僅在于如果一個局部變量的類型名很長的時候,可以幫助我們少寫點代碼。
你是否還在尋找穩定的海外服務器提供商?創新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統配攻擊溯源,準確流量調度確保服務器高可用性,企業級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧
文章名稱:Java多態-創新互聯
文章出自:http://vcdvsql.cn/article24/jgpje.html
成都網站建設公司_創新互聯,為您提供網站制作、品牌網站建設、網站設計、網站改版、網頁設計公司、企業建站
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯