1 繼承的概念
如果類 B 具有類 A 的全部屬性和方法,而且又具有自己特有的某些屬性和方法,則把類 A 稱作一般類,把類 B 稱作特殊類。
在面向?qū)ο蟪绦蛟O(shè)計(jì)中運(yùn)用繼承原則,就是在每個(gè)由一般類和特殊類形成的一般 - 特殊結(jié)構(gòu)中,把一般類的對(duì)象實(shí)例和所有特殊類的對(duì)象實(shí)例都共同具有的屬性和操作一次性地在一般類中進(jìn)行顯式的定義,在特殊類中不再重復(fù)地定義一般類中已經(jīng)定義的東西,但是在語義上,特殊類卻自動(dòng)地、隱含地?fù)碛兴囊话泐悾ㄒ约八懈蠈拥囊话泐悾┲卸x的屬性和操作。
特殊類的對(duì)象擁有其一般類的全部或部分屬性與方法,稱作特殊類對(duì)一般類的繼承。
繼承所表達(dá)的就是一種對(duì)象之間的相交關(guān)系,它使得某類對(duì)象可以繼承另外一類對(duì)象的數(shù)據(jù)成員和成員方法。
若類 B 繼承類 A 時(shí),則屬于 B 的對(duì)象便具有類 A 的全部或部分性質(zhì)(數(shù)據(jù)屬性)和功能(操作)。
我們稱被繼承的類 A 為基類、父類或超類,而稱繼承類 B 為 A 的派生類或子類。
繼承避免了對(duì)一般類和特殊類之間共同特征進(jìn)行的重復(fù)描述。
2 繼承的特征
繼承關(guān)系是傳遞的。繼承是在一些比較一般的類的基礎(chǔ)上構(gòu)造、建立和擴(kuò)充新類的最有效的手段。
繼承簡化了人們對(duì)事物的認(rèn)識(shí)和描述,能清晰體現(xiàn)相關(guān)類間的層次結(jié)構(gòu)關(guān)系。
提供軟件復(fù)用功能。
通過增強(qiáng)一致性來減少模塊間的接口和界面,大大增加程序的易維護(hù)性。
提供多重繼承機(jī)制。從理論上說,一個(gè)類可以是多個(gè)一般類的特殊類,它可以從多個(gè)一般類中繼承屬性和方法,這便是多重繼承。而 Java 出于安全性和可靠性的考慮,僅支持單重繼承,而通過使用接口機(jī)制來實(shí)現(xiàn)多重繼承。
3 Java 用 extends 指明繼承關(guān)系
在 Java 程序設(shè)計(jì)中,繼承是通過 extends 關(guān)鍵字來實(shí)現(xiàn)的。
在定義類時(shí)使用 extends 關(guān)鍵字指明新定義類的父類,新定義的類稱為指定父類的子類,這樣就在兩個(gè)類之間建立起了繼承關(guān)系。
這個(gè)新定義的子類可以從父類那里繼承所有非 private 的屬性和方法作為自己的成員。
實(shí)際上,在定義一個(gè)類而不給出 extends 關(guān)鍵字及父類名時(shí),默認(rèn)這個(gè)類是系統(tǒng)類 Object 的子類。
3.1 數(shù)據(jù)成員的繼承
子類可以繼承父類的所有非私有的數(shù)據(jù)成員。
3.2 數(shù)據(jù)成員的隱藏
數(shù)據(jù)成員的隱藏是指在子類中重新定義一個(gè)與父類中已經(jīng)定義的數(shù)據(jù)成員名完全相同的數(shù)據(jù)成員,即子類擁有了兩個(gè)相同名字的數(shù)據(jù)成員,一個(gè)是繼承父類的,另一個(gè)是自己定義的。
當(dāng)子類引用這個(gè)同名的數(shù)據(jù)成員時(shí),默認(rèn)操作是它自己定義的數(shù)據(jù)成員,而把從父類那里繼承來的數(shù)據(jù)成員“隱藏”起來。
當(dāng)子類要引用繼承自父類的同名數(shù)據(jù)成員時(shí),可使用關(guān)鍵字 super 引導(dǎo)。
3.3 成員方法的繼承
子類可以繼承父類的非私有成員方法。
3.4 成員方法的覆蓋(Overload)
子類可以重新定義與父類同名的成員方法,實(shí)現(xiàn)對(duì)父類方法的覆蓋。
方法的覆蓋與數(shù)據(jù)成員的隱藏的不同之處在于:
子類隱藏父類的數(shù)據(jù)成員只是使之不可見,父類同名的數(shù)據(jù)成員在子類對(duì)象中仍然占有自己獨(dú)立的內(nèi)存空間;
子類方法對(duì)父類同名方法的覆蓋將清除父類方法占用的內(nèi)存,從而使父類方法在子類對(duì)象中不復(fù)存在。
需要注意的是:子類在重新定義父類已有的方法時(shí),應(yīng)保持與父類完全相同的方法名、返回值類型和參數(shù)列表,否則就不是方法的覆蓋,而是子類定義自己特有的方法,與父類的方法無關(guān)。
4 this 與 super
4.1 this 的使用場合
在方法內(nèi)借助 this 來明確表示引用的是類的數(shù)據(jù)成員,而不是形參或局部變量,從而提高程序的可讀性。
簡單地說,this 代表了當(dāng)前對(duì)象的一個(gè)引用,可將其理解為對(duì)象的另一個(gè)名字,通過這個(gè)名字可以順利地訪問對(duì)象、修改對(duì)象的數(shù)據(jù)成員、調(diào)用對(duì)象的方法。
this 的使用場合主要有以下三種:
用來訪問當(dāng)前對(duì)象的數(shù)據(jù)成員:
this.數(shù)據(jù)成員
用來訪問當(dāng)前對(duì)象的成員方法:
this.成員方法(參數(shù))
當(dāng)有重載的構(gòu)造方法時(shí),用來引用同類的其他構(gòu)造方法:
this(參數(shù))
4.2 super 的使用場合
super 表示的是當(dāng)前對(duì)象的直接父類對(duì)象,是當(dāng)前對(duì)象的直接父類對(duì)象的引用。
所謂直接父類是相對(duì)于當(dāng)前對(duì)象的其他“祖先”類而言。
若子類的數(shù)據(jù)成員或成員方法名與父類的數(shù)據(jù)成員或成員方法名相同時(shí),當(dāng)要調(diào)用父類的同名方法或使用父類的同名數(shù)據(jù)成員,則可用關(guān)鍵字 super 來指明父類的數(shù)據(jù)成員和方法。
super 的使用場合有三種:
用來訪問直接父類隱藏的數(shù)據(jù)成員:
super.數(shù)據(jù)成員
用來調(diào)用直接父類中被覆蓋的成員方法:
super.成員方法(參數(shù))
用來調(diào)用直接父類的構(gòu)造方法:
super(參數(shù))
5 構(gòu)造方法的重載與繼承
5.1 構(gòu)造方法的重載
一個(gè)類的若干個(gè)構(gòu)造方法之間可以相互調(diào)用。
當(dāng)一個(gè)構(gòu)造方法需要調(diào)用另一個(gè)構(gòu)造方法時(shí),可以使用關(guān)鍵字 this,同時(shí)這個(gè)調(diào)用語句應(yīng)該是整個(gè)構(gòu)造方法的第一個(gè)可執(zhí)行語句。
使用關(guān)鍵字 this 來調(diào)用同類的其他構(gòu)造函數(shù)時(shí),優(yōu)點(diǎn)同樣是可以最大限度地提高對(duì)已有代碼的利用程度,提高程序的抽象度和封裝性,減少程序的維護(hù)工作量。
5.2 構(gòu)造方法的繼承
子類可以繼承父類的構(gòu)造方法,構(gòu)造方法的繼承遵循以下的原則:
子類無條件地繼承父類的不含參數(shù)的構(gòu)造方法。
如果子類自己沒有構(gòu)造方法,則它將繼承父類的無參數(shù)構(gòu)造方法作為自己的構(gòu)造方法;如果子類自己定義了構(gòu)造方法,則在創(chuàng)建新對(duì)象時(shí),它將先執(zhí)行繼承自父類的無參數(shù)構(gòu)造方法,然后再執(zhí)行自己的構(gòu)造方法。
對(duì)于父類含參數(shù)的構(gòu)造方法,子類可以通過在自己的構(gòu)造方法中使用 super 關(guān)鍵字來調(diào)用它,但這個(gè)調(diào)用語句必須是子類構(gòu)造方法的第一個(gè)可執(zhí)行語句。
6 向方法傳遞對(duì)象
傳遞給方法的參數(shù)可以是表達(dá)式(如常量、變量)、對(duì)象等。
傳遞給方法的參數(shù)若是變量,則只能由實(shí)參傳遞給形參,而不能由形參帶回,它是一種單向值傳遞。
在方法的引用過程中,對(duì)于形參變量值的修改并不影響實(shí)參變量的值。
但是,傳遞給方法的參數(shù)若是對(duì)象,則方法可以對(duì)其做永久性修改。
7 類轉(zhuǎn)換
類轉(zhuǎn)換就是指父類對(duì)象與子類對(duì)象之間在一定條件下的相互轉(zhuǎn)換。
父類對(duì)象與子類對(duì)象之間相互轉(zhuǎn)換規(guī)則如下:
父類對(duì)象與子類對(duì)象之間可以隱式轉(zhuǎn)換(也稱默認(rèn)轉(zhuǎn)換),也可以顯式轉(zhuǎn)換(也稱強(qiáng)制轉(zhuǎn)換)。
處于相同類層次的類的對(duì)象不能進(jìn)行轉(zhuǎn)換。
子類對(duì)象可以轉(zhuǎn)換成父類對(duì)象,但對(duì)數(shù)據(jù)成員的引用必須使用強(qiáng)制轉(zhuǎn)換。
類轉(zhuǎn)換格式如下:
(子類)父類
或
(父類)子類
8 繼承與封裝的關(guān)系
在面向?qū)ο笙到y(tǒng)中,封裝性主要指的是對(duì)象的封裝性,即將屬于某一類的一個(gè)具體對(duì)象封裝起來,使其數(shù)據(jù)和操作成為一個(gè)整體。
在引入了繼承機(jī)制的面向?qū)ο笙到y(tǒng)中,對(duì)象依然是封裝得很好的實(shí)體,其他對(duì)象與它進(jìn)行通訊的途徑仍然只有一條,那就是發(fā)送消息。
類機(jī)制是一種靜態(tài)機(jī)制,不管是基類還是派生類,對(duì)于對(duì)象來說,它仍然是一個(gè)類的實(shí)例,既可能是基類的實(shí)例,也可能是派生類的實(shí)例。
因此,繼承機(jī)制的引入絲毫沒有影響對(duì)象的封裝性。
繼承和封裝機(jī)制還具有一定的相似性,它們都是一種共享代碼的手段。
繼承是一種靜態(tài)共享代碼的手段,通過派生類對(duì)象的創(chuàng)建,可以接收某一消息,啟動(dòng)其基類所定義的代碼段,從而使基類和派生類共享了這一段代碼。
封裝機(jī)制所提供的是一種動(dòng)態(tài)共享代碼的手段,通過封裝,我們可將一段代碼定義在一個(gè)類中,在另一個(gè)類所定義的操作中,我們可以通過創(chuàng)建該類的實(shí)例,并向它發(fā)送消息而啟動(dòng)這一段代碼,同樣也達(dá)到共享的目的。