【JavaSE系列】 第九话 —— 多态那些事儿
?導(dǎo)航小助手?
? 🍚前言
? 🍞思維導(dǎo)圖
? 🧇一、多態(tài)的概念
? 🧀二、向上轉(zhuǎn)型和向下轉(zhuǎn)型
? ? ? ? ? ? ? 🥡🥡2.1 向上轉(zhuǎn)型
? ? ? ? ? ? ? 🥨🥨2.2?什么是向上轉(zhuǎn)型
? ? ? ? ? ? ? 🥐🥐2.3?三種常見的向上轉(zhuǎn)型
? ? ? ? ? ? ? ? ? ? ? ? 🍔🍔🍔2.3.1?直接賦值
? ? ? ? ? ? ? ? ? ? ? ? 🍜🍜🍜2.3.2?作為方法的參數(shù)
? ? ? ? ? ? ? ? ? ? ? ? 🎂🎂🎂2.3.3?作為方法的返回值
? ? ? ? ? ? ? 🍤🍤2.4?向下轉(zhuǎn)型(這個(gè)了解即可)
? 🍰三、方法重寫
? ? ? ? ? ? ? 🍣🍣3.1 方法重寫的概念
? ? ? ? ? ? ? 🦪🦪3.2 方法重寫的規(guī)定
? ? ? ? ? ? ? 🥩🥩3.3 在IDEA中使用重寫的快捷方式???????
? ? ? ? ? ? ? 🍱🍱3.4 方法重寫中所要注意的細(xì)節(jié)
? 🍛四、多態(tài)
? ? ? ? ? ? ? 🍖🍖4.1 什么是多態(tài)
? ? ? ? ? ? ? 🥮🥮4.2 多態(tài)產(chǎn)生的前提
? 🍝五、理解多態(tài)
? 🥣六、多態(tài)的優(yōu)缺點(diǎn)
? ? ? ? ? ? ? 🥗🥗6.1 使用多態(tài)的好處???????
? ? ? ? ? ? ? 🍗🍗6.2 多態(tài)的缺點(diǎn)
? 🍲七、避免在構(gòu)造方法中調(diào)用重寫的方法
? 🍎寫在最后
前言
? ? ? ?本篇博客 博主來介紹 Java的三大特性的最后一個(gè) 特性 —— 多態(tài);
? ? ? ?當(dāng)然,也包括多態(tài)所涉及的多方面內(nèi)容;
? ? ? ?現(xiàn)在,拉長(zhǎng)耳朵,提高警覺,端起你們的小板凳;
? ? ? ?且聽我細(xì)細(xì)道來......
思維導(dǎo)圖
?
一、多態(tài)的概念
? ? ? ?多態(tài),
? ? ? ?從語(yǔ)文的層次上來說:一種事務(wù),多種形態(tài);這句話不算對(duì),但也不算錯(cuò);
? ? ? ?但是,我們需要從程序的角度上來介紹:去完成某個(gè)行為,當(dāng)不同的對(duì)象去完成時(shí),會(huì)產(chǎn)生不同的狀態(tài),這就是多態(tài)。
? ? ? ?比如說,如下圖所示:同樣是一個(gè)打印機(jī),去打印相同的照片;但是,交給彩色打印機(jī)打印出來的就是彩色的照片;交給黑白打印機(jī)打印出來的就是黑白照片;它們完成的動(dòng)作都是“打印”;這就是一種多態(tài);
? ? ? ?再比如說,如下圖所示,去“吃飯”,對(duì)于小貓來說,吃的是“貓糧”;但對(duì)于小狗來說,吃的確是“狗糧”;他們完成的都是“吃飯”這個(gè)行為,但是卻“吃出不同的結(jié)果來”; 這也是一種多態(tài);
總的來說,同一件事情,發(fā)生在不同的對(duì)象上,會(huì)產(chǎn)生不同的結(jié)果。?
聽到這里,是不是還是對(duì)于 多態(tài) 有點(diǎn)頭暈;
那么,要想真正了解多態(tài),我們還是需要從三個(gè)方面來介紹:
下面,我會(huì)一一的介紹......
二、向上轉(zhuǎn)型和向下轉(zhuǎn)型
2.1 向上轉(zhuǎn)型
? ? ? ?當(dāng)然的是,有了 向上轉(zhuǎn)型,那么肯定也會(huì)有向下轉(zhuǎn)型,
向下轉(zhuǎn)型 會(huì)在后面講到......
2.2?什么是向上轉(zhuǎn)型
? ? ? ?首先介紹一段平平常常的繼承代碼:
package Demo1; class Animal {public String name;public int age;public void eat() {System.out.println(this.name+"吃飯!");} }class Cat extends Animal {public String hair;public void mew() {System.out.println(this.name+"正在叫!");} }public class TestDemo1 {public static void main(String[] args) {Cat cat = new Cat();cat.mew();} }? ? ? ?那么,如果現(xiàn)在拋開 繼承 不談,直接用Animal類 new一個(gè)animal對(duì)象,可以發(fā)現(xiàn),animal對(duì)象訪問不了Animal類 里面沒有的成員變量 或成員方法:
? ? ? ?接下來,可以來講一講 向上轉(zhuǎn)型 的知識(shí)了:
? ? ? ?這里的 上 指的是 父類,那么 下 指的就是 子類;
? ? ? ? 那么,把子類給父類是什么意思呢?
//即:定義類一個(gè) cat//可以用animal來接收//也就是說,父類的引用 可以用來引用 子類的對(duì)象Cat cat = new Cat();Animal animal = cat;//也就是說,上面的兩行代碼,可以合并成下面一行代碼Animal animal = new Cat();//此時(shí),父類的引用 引用了 子類的對(duì)象,我們把這個(gè)就叫做 向上轉(zhuǎn)型? ? ? ?但是,此時(shí)又有一個(gè)新的問題;
? ? ? ?animal的類型是Animal,那么 此時(shí)它只能去訪問 類Animal 的成員變量和方法,去訪問 子類Cat的成員變量或方法的時(shí)候會(huì)報(bào)錯(cuò):
?
【總結(jié)】
? ? ? ?向上轉(zhuǎn)型,把原來的 子類的類型 轉(zhuǎn)換成了 父類的類型,那么,就只能去訪問 父類特有的成員方法或者成員變量。
2.3?三種常見的向上轉(zhuǎn)型
2.3.1?直接賦值
? ? ? ?所謂直接賦值,就是 上面的直接把 子類對(duì)象 給 父類 進(jìn)行引用:
/*Cat cat = new Cat();Animal animal = cat;*/Animal animal = new Cat();2.3.2?作為方法的參數(shù)
2.3.3?作為方法的返回值
2.4?向下轉(zhuǎn)型(這個(gè)了解即可)
前面已經(jīng)介紹過 向上轉(zhuǎn)型,那么 現(xiàn)在來介紹一下 向下轉(zhuǎn)型:
不過,現(xiàn)在來執(zhí)行一下這樣的操作:
此時(shí),運(yùn)行結(jié)果:
但是,向下轉(zhuǎn)型不安全(不介意使用向下轉(zhuǎn)型):
?我們還需要做以下修改 以保證其安全性:
【注意】
三、方法重寫
? ? ? ?由上面可知,父類引用引用了子類的對(duì)象;
? ? ? ?但是,在現(xiàn)實(shí)生活中,貓是吃貓糧的;
? ? ? ?那么,如果想改的話,肯定不可以在父類上面進(jìn)行修改的;
? ? ? ?畢竟,可能還有 其他的子類 來繼承父類;
? ? ? ?那么,如果想修改的話,就需要在子類里面重新取實(shí)現(xiàn)一遍這個(gè)方法的:
? ? ? ?然后,我們來對(duì)比一下 實(shí)現(xiàn)前后的結(jié)果:
沒有在子類里面寫eat方法:
在子類里面寫了eat方法:
?這是怎么回事呢?
——這就是馬上所要介紹的方法重寫。
3.1 方法重寫的概念
? ? ? ?重寫,也稱為覆蓋;
? ? ? ?重寫,是子類對(duì)父類 非靜態(tài)、非private修飾、非final修飾、非構(gòu)造方法 等的實(shí)現(xiàn)過程進(jìn)行重新編寫;
? ? ? ?重寫的好處是:子類可以根據(jù)需要,定義特定的屬于自己的行為;如 上面的貓可以吃貓糧,狗可以吃狗糧。
3.2 方法重寫的規(guī)定
方法重寫滿足以下三個(gè)條件:
? ? ? ?當(dāng)在子類 方法重寫以后,那么就會(huì)調(diào)用的是 子類重寫的內(nèi)容。
? ? ? ?我們把這個(gè)現(xiàn)象叫做動(dòng)態(tài)綁定(這是多態(tài)的基礎(chǔ))
? ? ? ?傳送門:動(dòng)態(tài)綁定
? ? ? ?在上面所示例中,
? ? ? ?在編譯的時(shí)候,調(diào)用的還是 父類Animal的eat方法;
? ? ? ?但是,在運(yùn)行的時(shí)候,變成了子類Cat自己的eat方法;
? ? ? ?因此,動(dòng)態(tài)綁定又稱為 運(yùn)行時(shí)綁定,
? ? ? ?即:在程序運(yùn)行的時(shí)候才知道要調(diào)用誰。
? ? ? ?當(dāng)然,有了 動(dòng)態(tài)綁定,那肯定也有 靜態(tài)綁定:
? ? ? ?在編譯期間就已經(jīng)知道了 要調(diào)用的是誰,
? ? ? ?比如說 重載。
3.3 在IDEA中使用重寫的快捷方式
? ? ? ?當(dāng)然,在使用IDEA編譯器的時(shí)候 ,
? ? ? ?重寫不僅僅可以直接在子類上手敲出來的(上面的就是),而且還可以使用快捷鍵的方式:
?
【注意】上面的 @Override 就是重寫的意思。
?
3.4 方法重寫中所要注意的細(xì)節(jié)
?訪問限定符權(quán)限大小比較:
private < default < peotected < public??
?
四、多態(tài)
4.1 什么是多態(tài)
類的實(shí)現(xiàn)者所寫的代碼:
class Animal {public String name;public int age;public void eat() {System.out.println(this.name+"吃飯!父類Animal");} }class Cat extends Animal {public String hair;public void eat(){System.out.println(this.name+"吃貓糧!");}public void mew() {System.out.println(this.name+"正在叫!");} } class Dog extends Animal {public void eat(){System.out.println(this.name+"吃狗糧!");} }類的調(diào)用者所寫的代碼:
public static void function(Animal animal) {animal.eat();}public static void main(String[] args) {Cat cat = new Cat();Dog dog = new Dog();function(cat);function(dog);}?
所以運(yùn)行之后得到的結(jié)果不一樣:
? ? ? ?從上面可以得到,同一個(gè)方法,當(dāng)引用的對(duì)象不一樣的時(shí)候,這個(gè)方法所表現(xiàn)出來的行為是不一樣的;
? ? ? ?我們把這種思想就叫做 多態(tài)。?
4.2 多態(tài)產(chǎn)生的前提
思想:通過一個(gè)引用調(diào)用一個(gè)方法,由于引用的對(duì)象不同,所執(zhí)行的行為也是不一樣的;我們把這種思想就叫做多態(tài)的思想。
五、理解多態(tài)
現(xiàn)在再次回顧一下多態(tài):
場(chǎng)景:現(xiàn)在想畫一個(gè)圖形(圖形是未知的):
首先,創(chuàng)建父類:
class Shape {//省略了長(zhǎng)、寬、高等之類的屬性public void draw(){System.out.println("畫圖形!!!!!!");}}創(chuàng)建父類Shape只是畫父類,但是并沒有說明畫什么;
現(xiàn)在想畫各種各樣的圖形,那么就可以去重寫 Shape類里面的draw方法來滿足自己的需求:
class Cycle extends Shape {@Overridepublic void draw() {System.out.println("○");} }class Rect extends Shape {@Overridepublic void draw() {System.out.println(" ? ");} }class Triangle extends Shape {@Overridepublic void draw() {System.out.println("△");} }前面兩段代碼都是類的實(shí)現(xiàn)者寫的;
當(dāng)有一天作為用戶、作為類的調(diào)用者 想要畫出這些圖形,那么就可以這樣來做:
public static void drawMap(Shape shape) {shape.draw();}public static void main(String[] args) {Cycle cycle = new Cycle();Rect rect = new Rect();Triangle triangle = new Triangle();drawMap(cycle);drawMap(rect);drawMap(triangle);}那么,根據(jù)引用的對(duì)象不一樣,draw方法所表現(xiàn)的行為就不一樣;
這個(gè)就叫做 多態(tài)。
代碼示例結(jié)果:
由此可見,多態(tài)只是一種思想,需要滿足三個(gè)條件;
那么,多態(tài)到底有什么好處呢?
——其拓展能力非常強(qiáng):
如果突然說,現(xiàn)在想要畫一朵花:
那么只需要在這樣做即可:
class Flower extends Shape {@Overridepublic void draw() {System.out.println("?");} }測(cè)試類添上這個(gè)來測(cè)試:
drawMap(new Flower());代碼示例結(jié)果:
六、多態(tài)的優(yōu)缺點(diǎn)
6.1 使用多態(tài)的好處
(1)能夠降低代碼的 "圈復(fù)雜度" ,避免使用大量的 if-else語(yǔ)句;
? ? ? ? ? ??傳送門——圈復(fù)雜度??????
? ? ? ? ? ?說白了,可以簡(jiǎn)單粗暴的計(jì)算 一段代碼中條件語(yǔ)句和循環(huán)語(yǔ)句 出現(xiàn)的個(gè)數(shù),這個(gè)個(gè)數(shù)就稱為 "圈復(fù)雜度";
? ? ? ? ? ? 如果一個(gè)方法的 圈復(fù)雜度 太高,就需要考慮重構(gòu)。
(2)可擴(kuò)展能力強(qiáng);?
? ? ? ? ? ? 就是上面所說的 添加了一朵花的 示例。
6.2 多態(tài)的缺點(diǎn)
? ? ? ? ? ? ? ? ? ? ?代碼的運(yùn)行效率低。
七、避免在構(gòu)造方法中調(diào)用重寫的方法
class B {public B(){func();}public void func() {System.out.println("B.func() ");} }class D extends B {D(){super();}@Overridepublic void func() {System.out.println("D.func() ");} }public class Test {public static void main(String[] args) {D d = new D();} }代碼示例結(jié)果:
?【說明】
【注意】最好盡量不要寫類似的代碼——避免在構(gòu)造方法中調(diào)用重寫的方法。
寫在最后
? ? ? ?到現(xiàn)在,Java三大特性的最后一個(gè)特性——多態(tài)思想 就已經(jīng)告一段落了;
? ? ? ?由于博主水平有限,可能會(huì)出現(xiàn)一些表達(dá)不清楚,或者出現(xiàn)一些其他的情況,
? ? ? ?歡迎各位鐵汁們指出來,和博主一起改正,
? ? ? ?一起努力,共同進(jìn)步;
? ? ? ?好了,如果這篇博客對(duì)鐵汁們有幫助的話,可以送一個(gè)免費(fèi)的 贊 嘛;
? ? ? ?當(dāng)然,順手點(diǎn)個(gè)關(guān)注是再好不過的了......
?
總結(jié)
以上是生活随笔為你收集整理的【JavaSE系列】 第九话 —— 多态那些事儿的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue3运行npm run serve报
- 下一篇: java美元兑换,(Java实现) 美元