JAVA語言與面向對象程序設計 第五章 繼承與多態(tài)_第1頁
JAVA語言與面向對象程序設計 第五章 繼承與多態(tài)_第2頁
JAVA語言與面向對象程序設計 第五章 繼承與多態(tài)_第3頁
JAVA語言與面向對象程序設計 第五章 繼承與多態(tài)_第4頁
JAVA語言與面向對象程序設計 第五章 繼承與多態(tài)_第5頁
已閱讀5頁,還剩148頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、第第5章章 繼承與多態(tài)繼承與多態(tài)5.1 繼承繼承5.2 Java的繼承的繼承5.3 多態(tài)多態(tài)5.4 Java的重載的重載5.5 構造函數(shù)的繼承與重載構造函數(shù)的繼承與重載5.6 包包5.7 接口接口5.8 小結小結習題習題本章討論面向對象程序設計的另外兩個重要特點:本章討論面向對象程序設計的另外兩個重要特點:繼承和多態(tài)。繼承是面向對象程序設計方法中的一繼承和多態(tài)。繼承是面向對象程序設計方法中的一種重要手段,通過繼承可以更有效地組織程序結構,種重要手段,通過繼承可以更有效地組織程序結構,明確類間關系,并充分利用已有的類來完成更復雜、明確類間關系,并充分利用已有的類來完成更復雜、深入的開發(fā)。多態(tài)則可

2、以提高類的抽象度和封閉性,深入的開發(fā)。多態(tài)則可以提高類的抽象度和封閉性,統(tǒng)一一個或多個相關類對外的接口。本章最后還將統(tǒng)一一個或多個相關類對外的接口。本章最后還將討論接口和包。討論接口和包。5.1 繼承繼承在面向對象技術的各個特點中,繼承是最具有特色,在面向對象技術的各個特點中,繼承是最具有特色,也是與傳統(tǒng)方法最不相同的一個。繼承實際上是存也是與傳統(tǒng)方法最不相同的一個。繼承實際上是存在于面向對象程序中的兩個類之間的一種關系。當在于面向對象程序中的兩個類之間的一種關系。當一個類獲取另一個類中所有非私有的數(shù)據(jù)和操作的一個類獲取另一個類中所有非私有的數(shù)據(jù)和操作的定義作為自己的部分或全部成分時,就稱這兩

3、個類定義作為自己的部分或全部成分時,就稱這兩個類之間具有繼承關系。被繼承的類稱為父類或超類,之間具有繼承關系。被繼承的類稱為父類或超類,繼承了父類或超類的所有數(shù)據(jù)和操作的類稱為子類。繼承了父類或超類的所有數(shù)據(jù)和操作的類稱為子類。一個父類可以同時擁有多個子類,這時這個父類實一個父類可以同時擁有多個子類,這時這個父類實際上是所有子類的公共域和公共方法的集合,而每際上是所有子類的公共域和公共方法的集合,而每一個子類則是父類的特殊化,是對公共域和方法在一個子類則是父類的特殊化,是對公共域和方法在功能、內(nèi)涵方面的擴展和延伸。現(xiàn)仍以電話卡為例,功能、內(nèi)涵方面的擴展和延伸。現(xiàn)仍以電話卡為例,圖圖5.1列舉了

4、各種電話卡類的層次結構、域和方法。列舉了各種電話卡類的層次結構、域和方法。圖圖 5.1 各種電話卡類及其間的繼承關系各種電話卡類及其間的繼承關系從圖從圖5.1可以看出,面向對象的繼承關系很符合人們可以看出,面向對象的繼承關系很符合人們的日常思維模式。電話卡分為無卡號、有卡號兩大的日常思維模式。電話卡分為無卡號、有卡號兩大類,無卡號的電話卡可以細分為磁卡、類,無卡號的電話卡可以細分為磁卡、IC卡等,有卡等,有卡號的電話卡可分為卡號的電話卡可分為IP電話卡和電話卡和200電話卡等。其電話卡等。其中,電話卡這個抽象概念對應的電話卡類是所有其中,電話卡這個抽象概念對應的電話卡類是所有其他類的父類,它是

5、所有電話卡的公共屬性的集合。他類的父類,它是所有電話卡的公共屬性的集合。這些公共屬性包括卡中剩余金額等靜態(tài)的數(shù)據(jù)屬性,這些公共屬性包括卡中剩余金額等靜態(tài)的數(shù)據(jù)屬性,以及撥打電話、查詢余額等動態(tài)的行為屬性。將電以及撥打電話、查詢余額等動態(tài)的行為屬性。將電話卡具體化、特殊化,就分別派生出兩個子類:無話卡具體化、特殊化,就分別派生出兩個子類:無卡號電話卡和有卡號電話卡??ㄌ栯娫捒ê陀锌ㄌ栯娫捒?。這兩個子類一方面繼承了父類電話卡的所有屬性這兩個子類一方面繼承了父類電話卡的所有屬性(包包括域與方法括域與方法),即它們也擁有剩余金額、撥打電話、,即它們也擁有剩余金額、撥打電話、查詢余額等數(shù)據(jù)和操作,另一方

6、面它們又根據(jù)自己查詢余額等數(shù)據(jù)和操作,另一方面它們又根據(jù)自己對原有的父類概念的明確和限定,專門定義了適用對原有的父類概念的明確和限定,專門定義了適用于本類特殊需要的特殊屬性,如,對于所有的有卡于本類特殊需要的特殊屬性,如,對于所有的有卡號電話卡,應該有卡號、密碼、接入號碼等域和登號電話卡,應該有卡號、密碼、接入號碼等域和登錄交換機的行為,這些屬性對無卡號電話卡是不適錄交換機的行為,這些屬性對無卡號電話卡是不適合的。從有卡號電話卡到合的。從有卡號電話卡到IP電話卡和電話卡和200電話卡的電話卡的繼承遵循完全相同的原則。繼承遵循完全相同的原則。使用繼承的主要優(yōu)點,是使得程序結構清晰,降低使用繼承的

7、主要優(yōu)點,是使得程序結構清晰,降低編碼和維護的工作量。仍以圖編碼和維護的工作量。仍以圖5.1為例。剩余金額為例。剩余金額是所有電話卡共有的屬性,第一種實現(xiàn)方案是為每是所有電話卡共有的屬性,第一種實現(xiàn)方案是為每一個電話卡類中都定義自己的剩余金額域;第二種一個電話卡類中都定義自己的剩余金額域;第二種實現(xiàn)方案是僅在抽象的電話卡父類中定義剩余金額實現(xiàn)方案是僅在抽象的電話卡父類中定義剩余金額域,其他類則從它那里繼承。因此第一種方案相對域,其他類則從它那里繼承。因此第一種方案相對于第二種方案,代碼量要多出若干倍。同時,當公于第二種方案,代碼量要多出若干倍。同時,當公共屬性發(fā)生修改時,第一種方案需要在每個類

8、中做共屬性發(fā)生修改時,第一種方案需要在每個類中做相應的修改,而第二種方案只需要在父類中修改一相應的修改,而第二種方案只需要在父類中修改一次即可,不但維護的工作量大大減少,而且也避免次即可,不但維護的工作量大大減少,而且也避免了在第一種方案中可能出現(xiàn)的修改遺漏。了在第一種方案中可能出現(xiàn)的修改遺漏。在面向對象的繼承特性中,還有一個關于單重繼承在面向對象的繼承特性中,還有一個關于單重繼承和多重繼承的概念。所謂單重繼承,是指任何一個和多重繼承的概念。所謂單重繼承,是指任何一個類都只有一個單一的父類;而多重繼承是指一個類類都只有一個單一的父類;而多重繼承是指一個類可以有一個以上的父類,它的靜態(tài)的數(shù)據(jù)屬性

9、和操可以有一個以上的父類,它的靜態(tài)的數(shù)據(jù)屬性和操作從所有這些父類中繼承。采用單重繼承的程序結作從所有這些父類中繼承。采用單重繼承的程序結構比較簡單,如圖構比較簡單,如圖5.1所示的是單純的樹狀結構,所示的是單純的樹狀結構,掌握、控制起來相對容易;而支持多重繼承的程序,掌握、控制起來相對容易;而支持多重繼承的程序,其結構則是復雜的網(wǎng)狀,設計、實現(xiàn)都比較復雜。其結構則是復雜的網(wǎng)狀,設計、實現(xiàn)都比較復雜。但是現(xiàn)實世界的實際問題,它們的內(nèi)部結構多為復但是現(xiàn)實世界的實際問題,它們的內(nèi)部結構多為復雜的網(wǎng)狀,用多重繼承的程序模擬起來比較自然,雜的網(wǎng)狀,用多重繼承的程序模擬起來比較自然,而單重繼承的程序要解決

10、這些問題,則需要其他的而單重繼承的程序要解決這些問題,則需要其他的一些輔助措施。一些輔助措施。C+是開發(fā)人員熟悉的支持多重繼是開發(fā)人員熟悉的支持多重繼承的面向對象的編程語言,而本書中介紹的承的面向對象的編程語言,而本書中介紹的Java語語言,出于安全、可靠性的考慮,僅支持單重繼承。言,出于安全、可靠性的考慮,僅支持單重繼承。綜上所述,在面向對象的程序設計中,采用繼承的綜上所述,在面向對象的程序設計中,采用繼承的機制來組織、設計系統(tǒng)中的類,可以提高程序的抽機制來組織、設計系統(tǒng)中的類,可以提高程序的抽象程度,使之更接近于人類的思維方式,同時也可象程度,使之更接近于人類的思維方式,同時也可以提高程序

11、開發(fā)效率,降低維護的工作量。以提高程序開發(fā)效率,降低維護的工作量。5.2 Java的繼承的繼承5.2.1 派生子類派生子類Java中的繼承是通過中的繼承是通過extends關鍵字來實現(xiàn)的,在定關鍵字來實現(xiàn)的,在定義類時使用義類時使用extends關鍵字指明新定義類的父類,關鍵字指明新定義類的父類,就在兩個類之間建立了繼承關系。新定義的類稱為就在兩個類之間建立了繼承關系。新定義的類稱為子類,它可以從父類那里繼承所有非子類,它可以從父類那里繼承所有非private的屬性的屬性和方法作為自己的成員。和方法作為自己的成員。例例 5-1 實現(xiàn)圖實現(xiàn)圖5.1中電話卡類的繼承結構。中電話卡類的繼承結構。 1

12、: abstract class PhoneCard2: 3: double balance;4:5: abstract boolean performDial( );6: double getBalance( )7: 8: return balance;9: 10: 11: abstract class None-Number-PhoneCard extends PhoneCard12: 13: String phoneSetType;14:15: String getSetType( )16: 17: return phoneSetType;18: 19: 20: abstract cla

13、ss Number-PhoneCard extends PhoneCard21: 22: long cardNumber;23: int password;24: String connectNumber;25: boolean connected;26: 27: boolean performConnection(long cn,int pw)28: 29: if(cn = cardNumber & pw = password)30: 31: connected = true;32: return true;33: 34: else35: return false;36: 37: 3

14、8: class magCard extends None-Number-PhoneCard39: 40: String usefulArea;41:42: boolean performDial( )43: 44: if( balance 0.9)45: 46: balance -= 0.9;47: return true;48: 49: else50: return false;51: 52: 53: class IC-Card extends None-Number-PhoneCard54: 55: boolean performDial( )56: 57: if( balance 0.

15、5)58: 59: balance -= 0.9;60: return true;61: 62: else63: return false;64: 65: 66: class IP-Card extends Number-PhoneCard67: 68: Date expireDate;69: boolean performDial( )70: 71: if( balance 0.3 & expireDate.after(new Date( )72: 73: balance -= 0.3;74: return true;75: 76: else77: return false;78:

16、79: 80: class D200-Card extends Number-PhoneCard81: 82: double additoryFee;83: 84: boolean performDial( )85: 86: if( balance (0.5 + additoryFee )87: 88: balance -= (0.5 + additoryFee);89: return true;90: 91: else92: return false;93: 94: 例例5-1定義了定義了PhoneCard,None-Number-PhoneCard,Number-PhoneCard,mag

17、Card,IC-Card,IP-Card,D200-Card共七個類,其中共七個類,其中None-Number-PhoneCard類和類和Number-PhoneCard類是類是PhoneCard類派生出的子類;類派生出的子類;magCard類和類和IC-Card類是類是None-Number-PhoneCard類派生出的子類派生出的子類;類;IP-Card類和類和D200-Card類是類是Number-PhoneCard類派生出的子類。類派生出的子類。 可 以 注 意 到 , 例可 以 注 意 到 , 例 5 - 1 的 程 序 中 只 有 在 第的 程 序 中 只 有 在 第 3 句句(P

18、honeCard類中類中)定義了域定義了域balance,但是在第,但是在第44,46(magCard類中類中),第,第57,59(IC-Card類中類中),第,第71,73(IP-Card類中類中),第,第86,88(D200-Card類中類中)句中句中都使用了都使用了balance域,它們自身并未定義域,它們自身并未定義balance域,域,使用的使用的balance都是從父類都是從父類PhoneCard那里繼承來的。那里繼承來的。另外,另外,PhoneCard類在第類在第5句定義了一個抽象方法句定義了一個抽象方法performDial( ),它的兩個子類也是抽象類,可以,它的兩個子類也是

19、抽象類,可以不實現(xiàn)這個抽象方法,分別派生出來的不實現(xiàn)這個抽象方法,分別派生出來的4個電話卡個電話卡類不是抽象類,故而分別定義了針對自己具體情況類不是抽象類,故而分別定義了針對自己具體情況的的performDial( )方法。例如磁卡電話通話時沒有方法。例如磁卡電話通話時沒有優(yōu)惠時段,平均話費較高;優(yōu)惠時段,平均話費較高;200卡的話費較低,但卡的話費較低,但是有額外的附加費;是有額外的附加費;IP卡的話費最低,但是必須在卡的話費最低,但是必須在失效日期之前撥打電話。失效日期之前撥打電話。最后,第最后,第68句使用一個句使用一個java.util包中的包中的Java系統(tǒng)類系統(tǒng)類Date,每個,每

20、個Date類的對象代表一個具體的日期。第類的對象代表一個具體的日期。第71句中句中new Date( )表達式的作用是創(chuàng)建一個包含當表達式的作用是創(chuàng)建一個包含當前日期的前日期的Date類的對象,類的對象,after( )方法是方法是Date類的方類的方法 , 在 失 效 日 期 比 當 前 日 期 晚 時 ,法 , 在 失 效 日 期 比 當 前 日 期 晚 時 ,expireDate.after(new Date( )返回返回true,否則返回,否則返回false。5.2.2 域的繼承與隱藏域的繼承與隱藏1. 域的繼承域的繼承子類可以繼承父類的所有非私有域。例如各類電話子類可以繼承父類的所有

21、非私有域。例如各類電話卡類所包含的域分別為:卡類所包含的域分別為: PhoneCard類:類: double balance; None-Number-PhoneCard類:類: double balance; /繼承自父類繼承自父類PhoneCard String phoneSetType; Number-PhoneCard類:類: double balance; /繼承自父類繼承自父類PhoneCard long cardNumber; int password; String connectNumber; boolean connect;magCard類:類: double balanc

22、e; /繼承自父類繼承自父類None-Number-PhoneCard String phoneSetType; /繼承自父類繼承自父類None-Number- PhoneCard String usefulArea;IC-Card類:類: double balance; /繼承自父類繼承自父類None-Number-PhoneCard String phoneSetType; /繼承自父類繼承自父類None-Number-PhoneCardIP-Card類:類: double balance; /繼承自父類繼承自父類Number-PhoneCard long cardNumber; /繼承自

23、父類繼承自父類Number-PhoneCard int password; /繼承自父類繼承自父類Number-PhoneCard String connectNumber; /繼承自父類繼承自父類Number-PhoneCard boolean connect; /繼承自父類繼承自父類Number-PhoneCard Date expireDate;D200-Card類:類: double balance; /繼承自父類繼承自父類Number-PhoneCard long cardNumber; /繼承自父類繼承自父類Number-PhoneCard int password; /繼承自父類

24、繼承自父類Number-PhoneCard String connectNumber; /繼承自父類繼承自父類Number-PhoneCard boolean connect; /繼承自父類繼承自父類Number-PhoneCard double additoryFee; 可見父類的所有非私有域實際是各子類都擁有的域可見父類的所有非私有域實際是各子類都擁有的域的集合。子類從父類繼承域而不是把父類域的定義的集合。子類從父類繼承域而不是把父類域的定義部分復制一遍,這樣做的好處是減少程序維護的工部分復制一遍,這樣做的好處是減少程序維護的工作量。作量。2. 域的隱藏域的隱藏子類重新定義一個與從父類那里

25、繼承來的域變量完子類重新定義一個與從父類那里繼承來的域變量完全相同的變量,稱為域的隱藏。全相同的變量,稱為域的隱藏。例如,如果把例例如,如果把例5-1中第中第80到到94句定義的句定義的D200-Card方法修改為:方法修改為: 80: class D200-Card extends Number-PhoneCard81: 82: double additoryFee;83: double balance;84: boolean performDial( )85: 86: if( balance (0.5 + additoryFee )87: 88: balance -= (0.5 + add

26、itoryFee);89: return true;90: 91: else92: return false;93: 94: 在第在第83句增加定義了一個與從父類那里繼承來的句增加定義了一個與從父類那里繼承來的balance變量完全相同的變量。這樣修改后,變量完全相同的變量。這樣修改后,D200-Card類中的域變?yōu)椋侯愔械挠蜃優(yōu)椋篋200-Card類:類: double balance; /繼承自父類繼承自父類Number-PhoneCard double balance; /D200-Card類自己定義的域類自己定義的域 long cardNumber; /繼承自父類繼承自父類Number

27、-PhoneCard int password; /繼承自父類繼承自父類Number-PhoneCard String connectNumber; /繼承自父類繼承自父類Number-PhoneCard boolean connect; /繼承自父類繼承自父類Number-PhoneCard double additoryFee; 這時,子類中定義了與父類同名的屬性變量,即出這時,子類中定義了與父類同名的屬性變量,即出現(xiàn)了子類變量對同名父類變量的隱藏。這里所謂隱現(xiàn)了子類變量對同名父類變量的隱藏。這里所謂隱藏是指子類擁有了兩個相同名字的變量,一個繼承藏是指子類擁有了兩個相同名字的變量,一個繼承

28、自父類,另一個由自己定義;當子類執(zhí)行繼承自父自父類,另一個由自己定義;當子類執(zhí)行繼承自父類的操作時,處理的是繼承自父類的變量,而當子類的操作時,處理的是繼承自父類的變量,而當子類執(zhí)行它自己定義的方法時,所操作的就是它自己類執(zhí)行它自己定義的方法時,所操作的就是它自己定義的變量,而把繼承自父類的變量定義的變量,而把繼承自父類的變量“隱藏隱藏”起來。起來。參看下面的例參看下面的例5-2。例例 5-2 TestHiddenField.java 1: public class TestHiddenField2: 3: public static void main(String args)4: 5: D

29、200-Card my200 = new D200-Card( );6: my200.balance = 50.0;7: System.out.println(父類被隱藏的金額為:父類被隱藏的金額為:+my200.getBalance( );8:if(my200.performDial( )9: System.out.println(子類的剩余金額為:子類的剩余金額為:+my200.balance);10: 11:12:abstract class PhoneCard13: 14: double balance;15:16: abstract boolean performDial( );17

30、: double getBalance( )18: 19: return balance;20: 21: 22:abstract class Number-PhoneCard extends PhoneCard23: 24: long cardNumber;25: int password;26: String connectNumber;27: boolean connected;28: 29: boolean performConnection(long cn,int pw)30: 31: if(cn = cardNumber & pw = password)32: 33: con

31、nected = true;34: return true;35: 36: else37: return false;38: 39: 40: class D200-Card extends Number-PhoneCard41: 42: double additoryFee;43: double balance;44: 45: boolean performDial( )46: 47: if( balance (0.5 + additoryFee )48: 49: balance -= (0.5 + additoryFee);50: return true;51: 52: else53: re

32、turn false;54: 55: 圖圖5.2是例是例5-2的運行結果。的運行結果。 圖圖 5.2 例例5-2的運行結果的運行結果 例例5-2中,第中,第5句創(chuàng)建了一個句創(chuàng)建了一個D200-Card類的對象類的對象my200,這個對象有兩個,這個對象有兩個balance變量,一個繼承自變量,一個繼承自父類父類PhoneCard,另一個是在第,另一個是在第43句中重新定義的句中重新定義的自身的自身的balance變量。第變量。第6句為句為my200對象的對象的balance變量賦值,根據(jù)域隱藏的原則,這里是為變量賦值,根據(jù)域隱藏的原則,這里是為my200自自身的身的balance變量賦值。第變

33、量賦值。第7句輸出句輸出my200對象的對象的getBalance( )方法的返回值,這里的方法的返回值,這里的getBalance( )方方法是在父類法是在父類PhoneCard中定義的,它返回的是中定義的,它返回的是my200對象繼承自父類對象繼承自父類PhoneCard的的balance變量的變量的數(shù)值,這個數(shù)值,這個balance沒有被賦值,其數(shù)值是缺省的沒有被賦值,其數(shù)值是缺省的0.0。第。第8句調(diào)用句調(diào)用my200對象的對象的performDial( )方法撥方法撥打電話,修改打電話,修改my200對象自身的對象自身的balance變量。第變量。第9句輸出撥打電話之后,句輸出撥打電

34、話之后,my200對象的對象的balance變量的變量的數(shù)值。數(shù)值。5.2.3 方法的繼承與隱藏方法的繼承與隱藏1. 方法的繼承方法的繼承父類的非私有方法作為類的非私有成員,也可以被父類的非私有方法作為類的非私有成員,也可以被子類所繼承。如例子類所繼承。如例5-2中第中第7句調(diào)用的句調(diào)用的my200對象的對象的getBalance( )方法就繼承自父類方法就繼承自父類PhoneCard類。根類。根據(jù)方法的繼承關系,列舉各種電話卡所包含方法據(jù)方法的繼承關系,列舉各種電話卡所包含方法(僅列出方法頭僅列出方法頭)如下:如下: PhoneCard類:類: abstract boolean perfor

35、mDial( ); double getBalance( )None-Number-PhoneCard類:類: abstract boolean performDial( );/繼承自父類繼承自父類PhoneCard double getBalance( ) /繼承自父類繼承自父類PhoneCard String getSetType( )Number-PhoneCard類:類: abstract boolean performDial( ); /繼承自父類繼承自父類PhoneCard double getBalance( ) /繼承自父類繼承自父類PhoneCard boolean perf

36、ormConnection(long cn,int pw)magCard類:類: double getBalance( ) /繼承自父類繼承自父類None-Number-PhoneCard String getSetType( ) /繼承自父類繼承自父類None-Number-PhoneCard boolean performDial( )IC-Card類:類: double getBalance( ) /繼承自父類繼承自父類None-Number-PhoneCard String getSetType( ) /繼承自父類繼承自父類None-Number-PhoneCard boolean p

37、erformDial( )IP-Card類:類: boolean performDial( ) double getBalance( ) /繼承自父類繼承自父類Number-PhoneCard boolean performConnection(long cn,int pw) /繼承自父類繼承自父類Number-PhoneCardD200-Card類:類: boolean performDial( ) double getBalance( ) /繼承自父類繼承自父類Number-PhoneCard boolean performConnection(long cn,int pw) /繼承自父類

38、繼承自父類Number-PhoneCard各類的對象可以自由使用從父類那里繼承來的方法。各類的對象可以自由使用從父類那里繼承來的方法。2. 方法的覆蓋方法的覆蓋正像子類可以定義與父類同名的域,實現(xiàn)對父類域正像子類可以定義與父類同名的域,實現(xiàn)對父類域變量的隱藏一樣;子類也可以重新定義與父類同名變量的隱藏一樣;子類也可以重新定義與父類同名的方法,實現(xiàn)對父類方法的覆蓋的方法,實現(xiàn)對父類方法的覆蓋(Overload)。方法。方法的覆蓋與域的隱藏的不同之處在于:子類隱藏父類的覆蓋與域的隱藏的不同之處在于:子類隱藏父類的域只是使之不可見,父類的同名域在子類對象中的域只是使之不可見,父類的同名域在子類對象中

39、仍然占有自己的獨立的內(nèi)存空間;而子類方法對父仍然占有自己的獨立的內(nèi)存空間;而子類方法對父類同名方法的覆蓋將清除父類方法占用的內(nèi)存,從類同名方法的覆蓋將清除父類方法占用的內(nèi)存,從而使父類方法在子類對象中不復存在。例如上一小而使父類方法在子類對象中不復存在。例如上一小節(jié)列舉的各電話卡類的方法中,節(jié)列舉的各電話卡類的方法中,magCard,IC-Card,IP-Card,D200-Card四個類都定義了自己四個類都定義了自己的的performDial( )方法,所以它們從父類那里繼承方法,所以它們從父類那里繼承來的抽象的來的抽象的performDial( )就不存在了。就不存在了。在例在例5-2的的

40、D200-Card類中增加定義一個與從父類那類中增加定義一個與從父類那里繼承來的里繼承來的getBalance( )方法同名的方法,就可得方法同名的方法,就可得到例到例5-3。其運行結果如圖。其運行結果如圖5.3所示,可見此時調(diào)用所示,可見此時調(diào)用子類對象子類對象my200自己的自己的getBalance( )方法,返回的方法,返回的是是my200對象自己的對象自己的balance域。域。 圖圖 5.3 例例5-3的運行結果的運行結果 例例 5-3 TestOverLoad.java1: public class TestHiddenField2: 3: public static void

41、main(String args)4:5: D200-Card my200 = new D200-Card( );6: my200.balance = 50.0;7: System.out.println(父類被隱藏的金額為:父類被隱藏的金額為:+my200.getBalance( );8:if(my200.performDial( )9: System.out.println(子類的剩余金額為:子類的剩余金額為:+my200.balance);10: 11: 12: abstract class PhoneCard13: 14: double balance;15:16: abstract

42、boolean performDial( );17: double getBalance( )18: 19: return balance;20: 21: 22: abstract class Number-PhoneCard extends PhoneCard23: 24: long cardNumber;25: int password;26: String connectNumber;27: boolean connected;28: 29: boolean performConnection(long cn,int pw)30: 31: if(cn = cardNumber &

43、 pw = password)32: 33: connected = true;34: return true;35: 36: else37: return false;38: 39: 40: class D200-Card extends Number-PhoneCard41: 42: double additoryFee;43: double balance;44: 45: boolean performDial( )46: 47: if( balance (0.5 + additoryFee )48: 49: balance -= (0.5 + additoryFee);50: retu

44、rn true;51: 52: else53: return false;54: 55: double getBalance( )56: 57: return balance;58: 59: 5.2.4 this與與superthis和和super是常用來指代父類對象和子類對象的關鍵是常用來指代父類對象和子類對象的關鍵字。字。Java系統(tǒng)默認,每個類都缺省地具有系統(tǒng)默認,每個類都缺省地具有null,this和和super三個域,所以在任意類中都可以不加說三個域,所以在任意類中都可以不加說明而直接使用它們。其中明而直接使用它們。其中null代表代表“空空”, 代表一代表一個什么也沒有的個什么也沒

45、有的“空空”值。在定義一個對象但尚未值。在定義一個對象但尚未為其開辟內(nèi)存單元時可以指定這個對象為為其開辟內(nèi)存單元時可以指定這個對象為null。this和和super兩個域則與繼承有密切關系。兩個域則與繼承有密切關系。 1. thisthis表示的是當前對象本身,更準確地說,表示的是當前對象本身,更準確地說,this代表代表了當前對象的一個引用。對象的引用可以理解為對了當前對象的一個引用。對象的引用可以理解為對象的另一個名字,通過引用可以順利地訪問到對象,象的另一個名字,通過引用可以順利地訪問到對象,包括訪問、修改對象的域、調(diào)用對象的方法。這一包括訪問、修改對象的域、調(diào)用對象的方法。這一點有點像

46、點有點像C/C+語言中的指針,但是對象的引用與語言中的指針,但是對象的引用與內(nèi)存地址無關,它僅僅是對象的另一個名字。內(nèi)存地址無關,它僅僅是對象的另一個名字。一個對象可以有若干個引用,一個對象可以有若干個引用,this就是其中之一。利就是其中之一。利用用this可以調(diào)用當前對象的方法或使用當前對象的可以調(diào)用當前對象的方法或使用當前對象的域。例如,在域。例如,在D200-Card類中的類中的getBalance ( )方法方法需要訪問同一個對象的域需要訪問同一個對象的域balance,可以利用,可以利用this寫寫成:成: double getBalance( ) return this.bala

47、nce; 表示返回的是當前同一個對象的表示返回的是當前同一個對象的balance域,當然在域,當然在這種情況下這種情況下this也可以不加。更多的情況下,也可以不加。更多的情況下,this用用來把當前對象的引用作為參數(shù)傳遞給其他的對象或來把當前對象的引用作為參數(shù)傳遞給其他的對象或方法。例如,圖形界面的方法。例如,圖形界面的Java Applet程序程序(例例5-4):例例5-4 getDouble.java 1: import java.applet.*;2: import java.awt.*;3: import java.awt.event.*;4:5: public class getD

48、ouble extends Applet implements ActionListener6: 7: Label prompt;8: TextField input;9: double d = 0.0;10:11: public void init( )12: 13: prompt = new Label(請輸入一個浮點數(shù):請輸入一個浮點數(shù):);14: input = new TextField(10);15: add(prompt);16: add(input);17: input.addActionListener(this);18: 19: public void paint(Grap

49、hics g)20: 21: g.drawString(你輸入了數(shù)據(jù):你輸入了數(shù)據(jù): + d,10,50);22: 23: public void actionPerformed(ActionEvent e)24: 25: d = Double.valueOf(input.getText( ).doubleValue( );26: repaint( );27: 28: 例例5-4中,第中,第17句調(diào)用的句調(diào)用的addActionListener( )方法是方法是系統(tǒng)類系統(tǒng)類TextField的方法,調(diào)用這個方法要求提供一的方法,調(diào)用這個方法要求提供一個實現(xiàn)了個實現(xiàn)了ActionListener

50、接口的對象作為實際參數(shù)。接口的對象作為實際參數(shù)。第第5句中定義的用戶類句中定義的用戶類getDouble利用利用implements關關鍵字鍵字(接口及其實現(xiàn)將在本章后面介紹接口及其實現(xiàn)將在本章后面介紹)實現(xiàn)了實現(xiàn)了ActionListener接口,就使用接口,就使用this將當前將當前getDouble類的對象指定為調(diào)用類的對象指定為調(diào)用addActionListener( )方法的實方法的實際參數(shù)。際參數(shù)。2. supersuper表示的是當前對象的直接父類對象,是當前對表示的是當前對象的直接父類對象,是當前對象的直接父類對象的引用。所謂直接父類是相對于象的直接父類對象的引用。所謂直接父類

51、是相對于當前對象的其他當前對象的其他“祖先祖先”類而言的。例如,假設類類而言的。例如,假設類A派生出子類派生出子類B,B類又派生出自己的子類類又派生出自己的子類C,則,則B是是C的直接父類,而的直接父類,而A是是C的祖先類。同理,的祖先類。同理,Number-PhoneCard類是類是D200-Card類的直接父類,類的直接父類,PhoneCard類是類是D200-Card類的祖先類。類的祖先類。super代表代表的就是直接父類。的就是直接父類。例例 5-5 TestSuper.java 1: public class TestHiddenField2: 3: public static vo

52、id main(String args)4:5: D200-Card my200 = new D200-Card( );6: my200.balance = 50.0;7: System.out.println(父類被隱藏的金額為:父類被隱藏的金額為:+my200.getBalance( );8:if(my200.performDial( )9: System.out.println(子類的剩余金額為:子類的剩余金額為:+my200.balance);10: 11: 12: abstract class PhoneCard13: 14: double balance;15:16: abstra

53、ct boolean performDial( );17: double getBalance( )18: 19: return balance;20: 21: 22: abstract class Number-PhoneCard extends PhoneCard23: 24: long cardNumber;25: int password;26: String connectNumber;27: boolean connected;28: 29: boolean performConnection(long cn,int pw)30: 31: if(cn = cardNumber &a

54、mp; pw = password)32: 33: connected = true;34: return true;35: 36: else37: return false;38: 39: 40: class D200-Card extends Number-PhoneCard41: 42: double additoryFee;43: double balance;44: 45: boolean performDial( )46: 47: if( balance (0.5 + additoryFee )48: 49: balance -= (0.5 + additoryFee);50: r

55、eturn true;51: 52: else53: return false;54: 55: double getBalance( )56: 57: return super.balance;58: 59: 圖圖5.4是例是例5-5的運行結果。的運行結果。 圖圖 5.4 例例5-5的運行結果的運行結果 例例5-5中,第中,第57句句D200-Card類的方法類的方法getBalance( )返返回的是當前對象的回的是當前對象的super域的域的balance變量,當前對變量,當前對象的象的super域是域是D200-Card類的直接父類類的直接父類Number-PhoneCard的引用,的引

56、用,Number-PhoneCard的的balance變量是從變量是從PhoneCard類那里繼承來的。所以例類那里繼承來的。所以例5-5中,即使調(diào)用子類的中,即使調(diào)用子類的getBalance( )方法,返回的仍方法,返回的仍是沒有賦值的父類的是沒有賦值的父類的balance變量。變量。這里需要注意的是:這里需要注意的是:this和和super是屬于類的有特指的是屬于類的有特指的域,只能用來代表當前對象和當前對象的父對象,域,只能用來代表當前對象和當前對象的父對象,而不能像其他類的屬性一樣隨意引用。下面語句中而不能像其他類的屬性一樣隨意引用。下面語句中的用法都是錯誤的。的用法都是錯誤的。 D

57、200-Card my200 = new D200-Card( ) ;my200 . this . getBalance ( ) ; / 錯誤錯誤my200 . super . getBalance ( ) ; / 錯誤錯誤除了用來指代當前對象或父類對象的引用外,除了用來指代當前對象或父類對象的引用外,this和和super還有一個重要的用法,就是調(diào)用當前對象或還有一個重要的用法,就是調(diào)用當前對象或父類對象的構造函數(shù)。這部分內(nèi)容將在下面介紹。父類對象的構造函數(shù)。這部分內(nèi)容將在下面介紹。3. 父類對象與子類對象的轉換父類對象與子類對象的轉換類似于基本數(shù)據(jù)類型數(shù)據(jù)之間的強制類型轉換,存類似于基本數(shù)

58、據(jù)類型數(shù)據(jù)之間的強制類型轉換,存在繼承關系的父類對象和子類對象之間也可以在一在繼承關系的父類對象和子類對象之間也可以在一定條件下相互轉換。父類對象和子類對象的轉化需定條件下相互轉換。父類對象和子類對象的轉化需要注意如下原則:要注意如下原則:(1) 子類對象可以被視為是其父類的一個對象。子類對象可以被視為是其父類的一個對象。(2) 父類對象不能被當作是其某一個子類的對象。父類對象不能被當作是其某一個子類的對象。(3) 如果一個方法的形式參數(shù)定義的是父類對象,那如果一個方法的形式參數(shù)定義的是父類對象,那么調(diào)用這個方法時,可以使用子類對象作為實際參么調(diào)用這個方法時,可以使用子類對象作為實際參數(shù)。數(shù)。

59、(4) 如果父類對象引用指向的實際是一個子類對象如果父類對象引用指向的實際是一個子類對象(在在以前的某個時候根據(jù)以前的某個時候根據(jù)(1)把子類對象的引用賦值給把子類對象的引用賦值給這個父類對象的引用這個父類對象的引用),那么這個父類對象的引用,那么這個父類對象的引用可以用強制類型轉換轉化成子類對象的引用??梢杂脧娭祁愋娃D換轉化成子類對象的引用。參看下面的程序片斷:參看下面的程序片斷: class SuperClass /定義父類定義父類 int x; class SubClass extends SuperClass /定義子類定義子類 int y;char ch; public class

60、UseSuperSub /使用父類與子類使用父類與子類 SuperClass sc, sc-ref;SubClass sb, sb-ref;sc = new SuperClass( );sb = new SubClass( );sc-ref = sb; /父類引用可以指向子類對象父類引用可以指向子類對象sb-ref = (SubClass)sc-ref; /父類引用轉換成子類引用父類引用轉換成子類引用 5.3 多態(tài)多態(tài)多態(tài)是面向對象程序設計的又一個特殊特性。我們多態(tài)是面向對象程序設計的又一個特殊特性。我們已經(jīng)知道,利用面向過程的語言編程,主要工作是已經(jīng)知道,利用面向過程的語言編程,主要工作是編寫一個個過程或函數(shù)。這些過程和函數(shù)各

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論