Java必須學(xué)會(huì)的類的繼承與多態(tài)
繼承是類的一個(gè)很重要的特性,什么?你連繼承都不知道?你是想氣死爸爸好繼承爸爸的遺產(chǎn)嗎?(滑稽)
開個(gè)玩笑,這里的繼承跟我們現(xiàn)實(shí)生活的中繼承還是有很大區(qū)別的,一個(gè)類可以繼承另一個(gè)類,繼承的內(nèi)容包括屬性跟方法,被繼承的類被稱為父類或者基類,繼承的類稱為子類或者導(dǎo)出類,在子類中可以調(diào)用父類的方法和變量。在java中,只允許單繼承,也就是說 一個(gè)類最多只能顯示地繼承于一個(gè)父類。但是一個(gè)類卻可以被多個(gè)類繼承,也就是說一個(gè)類可以擁有多個(gè)子類。這就相當(dāng)于一個(gè)人不能有多個(gè)父親一樣(滑稽,老王表示不服)。
話不多說,先看栗子:
public class Employee {
private String name;//姓名
private double salary;//薪水
//構(gòu)造函數(shù)
public Employee(String name,int age,double salary){
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public int getAge() {
return age;
}
}
我們定義了一個(gè)Employee類(雇員類),并定義了一些簡(jiǎn)單的成員變量以及方法,接下來定義一個(gè)Manager類(經(jīng)理類)來繼承這個(gè)類。
public class Manager extends Employee{
private double bonus;//獎(jiǎng)金 //構(gòu)造器
public Manager(String name, double salary){
super(name,salary);
bonus = 0;
}
//設(shè)置獎(jiǎng)金
public void setBonus(double bonus) {
this.bonus = bonus;
}
//重載父類的getSalary方法
@Override
public double getSalary() {
double baseSalary = super.getSalary();
return baseSalary + bonus;
}
}
這里需要說明的是super跟this的使用,super是父類引用,可以用它來調(diào)用父類的方法和屬性,可以把它看作是父類跟子類溝通的橋梁,而this則是自身引用,可以通過它來調(diào)用自身的屬性和方法,在構(gòu)造器中我們使用了 super(name,salary); 這樣會(huì)調(diào)用父類的構(gòu)造函數(shù),
為什么Manager可以繼承Employee這個(gè)類呢?是因?yàn)樗鼈冎g存在is-a的關(guān)系,經(jīng)理也是一個(gè)雇員,有很多跟雇員相同的屬性如姓名,薪水,以及方法,如取姓名,取薪水,但是它也有自己獨(dú)有的屬性和方法,還可以重載父類的方法,如上面的getSalary。這里的Manager類對(duì)象,繼承了父類Employee的方法,因此Manager對(duì)象可以直接使用getName()方法,重載了getSalary方法,因此調(diào)用Manager對(duì)象的該方法時(shí),調(diào)用的是子類的getSalary方法,而不是父類,
那到底可以繼承父類的哪些信息呢?
1.子類可以繼承父類的成員變量
當(dāng)子類繼承了某個(gè)類之后,便可以使用父類中的成員變量,但是并不是完全繼承父類的所有成員變量。具體的原則如下:
1)能夠繼承父類的public和protected成員變量;不能夠繼承父類的private成員變量;
2)對(duì)于父類的包訪問權(quán)限成員變量,如果子類和父類在同一個(gè)包下,則子類能夠繼承;否則,子類不能夠繼承;
3)對(duì)于子類可以繼承的父類成員變量,如果在子類中出現(xiàn)了同名稱的成員變量,則會(huì)發(fā)生隱藏現(xiàn)象,即子類的成員變量會(huì)屏蔽掉父類的同名成員變量。如果要在子類中訪問父類中同名成員變量,需要使用super關(guān)鍵字來進(jìn)行引用。
2.子類繼承父類的方法
同樣地,子類也并不是完全繼承父類的所有方法。
1)能夠繼承父類的public和protected成員方法;不能夠繼承父類的private成員方法;
2)對(duì)于父類的包訪問權(quán)限成員方法,如果子類和父類在同一個(gè)包下,則子類能夠繼承;否則,子類不能夠繼承;
3)對(duì)于子類可以繼承的父類成員方法,如果在子類中出現(xiàn)了同名稱的成員方法,則稱為覆蓋,即子類的成員方法會(huì)覆蓋掉父類的同名成員方法。如果要在子類中訪問父類中同名成員方法,需要使用super關(guān)鍵字來進(jìn)行引用。
這里說了很多次public,private和protected,關(guān)于訪問權(quán)限好像沒還有正式介紹,這里來順便簡(jiǎn)單介紹一下吧:
Java類具有三種訪問控制符:private、protected和public,同時(shí)當(dāng)不寫這三個(gè)訪問控制符時(shí),表現(xiàn)為一種默認(rèn)的訪問控制狀態(tài)。因此,一共具有四種訪問控制級(jí)別。
具體訪問控制表現(xiàn)如下:
private修飾的屬性或方法為該類所特有,在任何其他類中都不能直接訪問;
default修飾的屬性或方法具有包訪問特性,同一個(gè)包中的其他類可以訪問;
protected修飾的屬性或方法在同一個(gè)中的其他類可以訪問,同時(shí)對(duì)于不在同一個(gè)包中的子類中也可以訪問;
public修飾的屬性或方法外部類中都可以直接訪問。
為什么要引入訪問權(quán)限這個(gè)概念呢?當(dāng)然是為了更好的封裝,就像制作一臺(tái)機(jī)器一樣,自然希望把所有的電線都藏在盒子里而不是大搖大擺的吊在外面被人吐槽,而且這樣也更加安全,只給用戶或用戶程序員看那些想給他們看的內(nèi)容就好了,其他的一律隱藏起來。
子類Manager雖然沒有繼承父類Employee的name和salary屬性,但不代表對(duì)這兩個(gè)屬性的操作沒有意義,可以理解成一個(gè)子類對(duì)象中包含有一個(gè)父類對(duì)象,打個(gè)比方,就像是我們組裝好幾款不同的電腦,為了方便起見可以選用同一款主機(jī)箱,里面配置了相同的電源和風(fēng)扇,而其它的配置每臺(tái)電腦都可以不一樣,甚至如果需要的話,某些電腦還可以更換一下風(fēng)扇和電源,雖然最后性能可能相去甚遠(yuǎn),但是從外表上看起來,它們都是差不多的。(當(dāng)然,如果你非要改裝的完全不一樣也是可以的)這里的配置好風(fēng)扇跟電源的主機(jī)箱就相當(dāng)于我們的父類,而不同的電腦就相當(dāng)于子類,子類可以調(diào)用父類的公開方法,如轉(zhuǎn)動(dòng)風(fēng)扇,但不能直接改變主機(jī)箱的顏色,因?yàn)楦割惒]有提供這樣的權(quán)限。但這不代表主機(jī)箱的顏色對(duì)于子類沒有用,它仍屬于子類的一部分,只是不能直接操作它罷了。
訪問權(quán)限的內(nèi)容就介紹到這里了,現(xiàn)在回歸到我們的繼承上來,下面是使用Manager類的一個(gè)栗子:
public class ManagerTest {
public static void main(String[] args){
Manager boss = new Manager("Frank",100000);//定義一個(gè)Manager變量
boss.setBonus(10000);//設(shè)置獎(jiǎng)金
Employee[] staff = new Employee[3];//創(chuàng)建一個(gè)Employee數(shù)組
//給數(shù)組賦值
staff[0] = boss;
staff[1] = new Employee("Alan",8000);
staff[2] = new Employee("Tom",9000);
//遍歷輸出數(shù)組元素
for (Employee e:staff)
System.out.println("name:"+e.getName()+" salary:"+e.getSalary());
}
}
這里我們定義了一個(gè)Employee數(shù)組,然后把一個(gè)Manager變量賦值給了Employee數(shù)組的第一個(gè)元素,看到這里,你也許會(huì)感到疑惑,不是說只能在相同類型的變量之間使用賦值操作嗎?確實(shí)如此,但是因?yàn)镸anager類是Employee的子類,一個(gè)Manager對(duì)象同時(shí)具有Employee的所有屬性跟方法,也就是說Employee能做的事情,它也同樣能做,所以,把Manager類的變量賦值給Employee變量是沒有問題的,但反之則不行,因?yàn)镸anager類有它自己的方法setBonus(),Employee是無法實(shí)現(xiàn)。在遍歷輸出的時(shí)候,我們把所有元素都當(dāng)成Employee對(duì)象來使用,輸出如下:
name:Frank salary:110000.0
name:Alan salary:8000.0
name:Tom salary:9000.0
boss變量,在調(diào)用getSalary方法的時(shí)候,顯然是調(diào)用了子類的方法,將基本薪水加上了獎(jiǎng)金之后才進(jìn)行返回。
那說了這么多,為什么非要使用繼承呢?
原因很簡(jiǎn)單,一個(gè)是可以實(shí)現(xiàn)代碼的復(fù)用,像這個(gè)例子一樣,Employee的getName方法被子類Manager復(fù)用了,Manager中可以直接使用這個(gè)方法,這樣可以省去很多代碼。
其次是可以實(shí)現(xiàn)多態(tài),說出來你可能不信,我們剛才的栗子已經(jīng)使用到了一個(gè)很偉大的概念——多態(tài),在遍歷輸出的時(shí)候,一個(gè)父類對(duì)象的引用指向了子類對(duì)象,并調(diào)用了子類方法。
那么這樣做的好處是什么呢?多態(tài)的意義何在?
簡(jiǎn)單,方便,繼續(xù)用我們剛才的栗子,假如我們現(xiàn)在有一個(gè)人事管理類,PersonnelManagement,需要對(duì)員工的信息進(jìn)行錄入,有一個(gè)record方法,我們?nèi)绻褂昧硕鄳B(tài)的特性,只需要給record方法傳入一個(gè)Employee對(duì)象即可,不管是經(jīng)理還是普通雇員都能使用相同的方式進(jìn)行處理,否則我們需要為經(jīng)理跟雇員分別設(shè)計(jì)一個(gè)方法,這樣也許覺得沒事,但如果現(xiàn)在又多了很多其它崗位,如總經(jīng)理,副經(jīng)理,經(jīng)理助手,人事部經(jīng)理,采購部經(jīng)理,這時(shí)候你還能為每個(gè)崗位設(shè)計(jì)一個(gè)方法嗎?顯然不現(xiàn)實(shí),而且這樣就失去了可擴(kuò)展性跟靈活性,把一門藝術(shù)活變成了體力活,這樣會(huì)讓你喪失對(duì)編程的樂趣。
所以,繼承跟多態(tài)其實(shí)也很簡(jiǎn)單,繼承就是使用extends來繼承父類的屬性跟方法,多態(tài)則是可以在合適的時(shí)候?qū)⒆宇悓?duì)象視為父類對(duì)象進(jìn)行統(tǒng)一處理,從而實(shí)現(xiàn)和增加代碼的復(fù)用度,讓你的代碼越來越風(fēng)騷。
至此類的繼承與多態(tài)就講解完畢了,歡迎大家繼續(xù)關(guān)注!喜歡我的教程的話記得動(dòng)動(dòng)小手點(diǎn)下推薦,也歡迎關(guān)注我的博客。
以上就是Java必須學(xué)會(huì)的類的繼承與多態(tài)的詳細(xì)內(nèi)容,更多關(guān)于Java類的繼承與多態(tài)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
如何避免在Java項(xiàng)目里大批量使用if-else?
想起剛開始接觸JAVA時(shí),若遇到大量流程判斷語句,幾乎滿屏都是if-else語句,多得讓自己都忘了哪里是頭,哪里是尾,但是,縱然滿屏是if-else,但彼時(shí)也沒有覺得多別扭.等到編程能力漸漸提升之后,再回過頭去看曾經(jīng)寫過的滿屏if-else時(shí),感覺全都是翔.....,需要的朋友可以參考下2021-06-06
Spring 事務(wù)事件監(jiān)控及實(shí)現(xiàn)原理解析
本文首先會(huì)使用實(shí)例進(jìn)行講解Spring事務(wù)事件是如何使用的,然后會(huì)講解這種使用方式的實(shí)現(xiàn)原理。感興趣的朋友跟隨小編一起看看吧2018-09-09
在同一個(gè)類中調(diào)用帶有@Transactional注解的方法示例
這篇文章主要為大家介紹了在同一個(gè)類中調(diào)用帶有@Transactional注解的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
Spring Boot中使用Server-Sent Events (SSE) 實(shí)
Server-Sent Events (SSE) 是HTML5引入的一種輕量級(jí)的服務(wù)器向?yàn)g覽器客戶端單向推送實(shí)時(shí)數(shù)據(jù)的技術(shù),本文主要介紹了Spring Boot中使用Server-Sent Events (SSE) 實(shí)現(xiàn)實(shí)時(shí)數(shù)據(jù)推送教程,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03
Eclipse 項(xiàng)目出現(xiàn)錯(cuò)誤(紅色嘆號(hào))解決方法
這篇文章主要介紹了Eclipse 項(xiàng)目出現(xiàn)錯(cuò)誤(紅色嘆號(hào))解決方法的相關(guān)資料,需要的朋友可以參考下2017-06-06

