版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第5章 繼承和多態(tài)繼承和多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計(jì)的重要內(nèi)容。繼承機(jī)制是實(shí)現(xiàn)軟件構(gòu)件復(fù)用的一種強(qiáng)有力的手段。多態(tài)性是面向?qū)ο缶幊痰闹匾匦?,是繼承產(chǎn)生的結(jié)果。Java語(yǔ)言很好的體現(xiàn)了繼承和多態(tài)性兩大特性。本章將討論用Java語(yǔ)言實(shí)現(xiàn)繼承和多態(tài)性,具體將介紹繼承概念、繼承的實(shí)現(xiàn)、抽象類的作用、方法的覆蓋以及用接口實(shí)現(xiàn)多繼承。5.1 繼承繼承是面向?qū)ο蟪绦蛟O(shè)計(jì)的三大概念之一,是面向?qū)ο蟪绦虻闹匾拍?,它使程序代碼復(fù)用成為可能。假設(shè)已經(jīng)定義和實(shí)現(xiàn)類DigitalProduction(代表數(shù)碼產(chǎn)品),需要定義一個(gè)新的應(yīng)用類MobilePhone(代表手機(jī))。由于手機(jī)是數(shù)碼產(chǎn)品的一種,所以沒有必要對(duì)類Di
2、gitalProduction中屬于數(shù)碼產(chǎn)品特征重新書寫代碼,只需要繼承類DigitalProduction的屬性特征即可。這樣,類MobilePhone通過(guò)繼承獲得了類DigitalProduction的數(shù)據(jù)和方法。由于類MobilePhone也具有自身的特征,如“進(jìn)網(wǎng)許可號(hào)”,可以為這些異于其他數(shù)碼產(chǎn)品的特征定義成員數(shù)據(jù)和成員方法。這樣,MobilePhone繼承于DigitalProduction,又具有新的屬性特征。圖5-1可以表示了兩個(gè)類之間的繼承關(guān)系。圖5-1 MobilePhone繼承DigitalProduction從這個(gè)意義上來(lái)說(shuō),繼承是指一個(gè)新的類繼承原有類的基本特性,并增
3、加新的特性。通俗地說(shuō),新的類與原有類之間體現(xiàn)了一種“is-a”關(guān)系。只要類和類之間存在的繼承關(guān)系,這種擴(kuò)展可以一直延續(xù)下去,它體現(xiàn)出類的層次結(jié)構(gòu)。例如,而類MobilePhone繼承于類DigitalProduction。而類IntelligentMobile(代表智能手機(jī))繼承于類MobilePhone。繼承可以分成兩大類型:?jiǎn)卫^承和多繼承。單繼承是一個(gè)類只能從一個(gè)類派生而來(lái),即只有一個(gè)父類。多繼承是一個(gè)類可以從多個(gè)類派生而來(lái),可以有多個(gè)父類。Java語(yǔ)言只支持單繼承,不支持多繼承。5.1.1 父類和子類Java語(yǔ)言中,繼承實(shí)際上是一個(gè)類擴(kuò)展一個(gè)已有的類。被擴(kuò)展的類是父類,而擴(kuò)展類是子類。子
4、類繼承了父類的類成員,并可以定義自己的獨(dú)特的屬性成員。通常體現(xiàn)了子類和父類之間是派生與被派生的關(guān)系。所以,有時(shí)稱父類為基類,而子類稱為派生類。Java語(yǔ)言也體現(xiàn)出類的層次結(jié)構(gòu)。Java語(yǔ)言中定義類java.lang.Object,它是所有類的父類。其他類無(wú)論是直接還是間接都是繼承了Object類,具有Object類的屬性,如在第4章中說(shuō)明的finalize()方法。比如,Java語(yǔ)言提供的類java.lang.String直接繼承于類java.lang.Object,而javax.swing.JOptionPane則是間接繼承于java.lang.Object,JOptionPane類具體繼承
5、情況見圖5-2。同樣,用戶自定義類也是直接或間接繼承于java.lang.Object類,具體實(shí)現(xiàn)見5.1.2。圖5-2 javax.swing.JOptionPane的繼承示意5.1.2 繼承的實(shí)現(xiàn)Java語(yǔ)言中是通過(guò)關(guān)鍵字extends來(lái)實(shí)現(xiàn)單繼承的。簡(jiǎn)單的實(shí)現(xiàn)格式如下:class 子類名 extends 父類名類體有一點(diǎn)要注意,如果在格式中沒有通過(guò)extends關(guān)鍵字來(lái)標(biāo)明父類名,這并不是意味著該類無(wú)父類,相反,它表示該類是java.lang.Object的子類。例5.1 類繼承的示例。public class BaseClass /定義一個(gè)類BaseClasspublic int in
6、tValue; /定義成員數(shù)據(jù)intValue;public BaseClass()intValue=3;System.out.println(Base Class 定義);public void showBaseMessage()System.out.println(Base Class 信息);public class DerivedClass extends BaseClass/定義類DerivedClasspublic DerivedClass()System.out.println(Derived Class 定義);public void showDerivedMessage()S
7、ystem.out.println(繼承而來(lái)的數(shù)據(jù): +intValue);/引用繼承的成員數(shù)據(jù)intValueSystem.out.println(Derived Class 信息);public static void main(String args)DerivedClass dc=new DerivedClass();dc.showBaseMessage();/引用繼承的成員方法showBaseMessage dc.showDerivedMessage(); System.exit(0); 圖5-3 例5.1的運(yùn)行結(jié)果例5.1定義了兩個(gè)類BaseClass和DerivedClass,其
8、中DerivedClass是BaseClass的子類,BaseClass是DerivedClass的父類。它們之間通過(guò)定義DerivedClass中增加extends子句來(lái)實(shí)現(xiàn)繼承關(guān)系。盡管類BaseClass的定義沒有用關(guān)鍵字extends來(lái)說(shuō)明父類,但實(shí)際上它是隱性的定義為java.lang.Object的子類。這樣,java.lang.Object、BaseClass和DerivedClass之間就構(gòu)成了繼承關(guān)系鏈。創(chuàng)建一個(gè)子類如DerivedClass的對(duì)象時(shí),會(huì)從上向下調(diào)用Object-BaseClass-DerivedClass繼承鏈的默認(rèn)構(gòu)造方法。從圖5-3中可以看出,創(chuàng)建一個(gè)D
9、erivedClass的對(duì)象之前先調(diào)用了父類BaseClass的默認(rèn)構(gòu)造方法。注意,如果在繼承鏈中存在某個(gè)父類沒有定義默認(rèn)構(gòu)造方法,會(huì)產(chǎn)生編譯錯(cuò)誤。不過(guò),盡管子類可以繼承父類的成員數(shù)據(jù)和成員方法,但并不意味著子類可以完全繼承父類的全部屬性。如果將例5.1中類BaseClass的公有(public)成員數(shù)據(jù)intValue改成私有(private)成員數(shù)據(jù),再編譯類Derived,會(huì)發(fā)現(xiàn)程序出現(xiàn)編譯錯(cuò)誤。這是由于類成員的訪問控制限制了類成員的可見性。父類的私有成員是不能被子類所繼承。就好比孩子繼承了父親的部分特征,而不是全部特征。5.2 抽象類在現(xiàn)實(shí)生活中,可以發(fā)現(xiàn)這樣的現(xiàn)象:許多實(shí)物抽象出成為
10、一個(gè)共同的類別,如“交通工具”,但是“交通工具”并直接對(duì)應(yīng)著實(shí)際存在的類別如卡車、自行車、三輪車等。又如“動(dòng)物”,并不特指具體的某個(gè)實(shí)際存在,它只是哺乳動(dòng)物、兩棲動(dòng)物等以有機(jī)物為食物,可運(yùn)動(dòng)生物的統(tǒng)稱?!敖煌üぞ摺?、“動(dòng)物”等這些只是作為一個(gè)抽象概念存在,對(duì)一組固定實(shí)現(xiàn)的抽象描述,并不對(duì)應(yīng)具體的概念。因此,在面向?qū)ο蟪绦蛟O(shè)計(jì)中,可以將這些抽象描述定義為抽象類,而這一組任意個(gè)可能的具體實(shí)現(xiàn)則表現(xiàn)為所有可能的派生類。由于抽象類對(duì)一組具體實(shí)現(xiàn)的抽象性描述,所以抽象體是不能修改的。通常抽象類不具備實(shí)際功能,只用來(lái)派生子類。5.2.1 抽象方法Java語(yǔ)言中,用關(guān)鍵字abstract修飾的方法為抽象方法
11、。語(yǔ)法格式形如:abstract 返回值類型 方法名(形式參數(shù));例如: abstract void showMessage();抽象方法只有方法頭沒有方法體,即只提供方法的規(guī)格說(shuō)明,沒有具體的實(shí)現(xiàn)。抽象方法只能出現(xiàn)在抽象類(見5.2.2)和接口(見5.4)中,其他類中定義會(huì)產(chǎn)生編譯錯(cuò)誤。有兩點(diǎn)必須注意:1)final關(guān)鍵字不能修飾抽象方法。這是因?yàn)閒inal是不可修改的方法是最終的方法,而抽象方法沒有方法體,能被派生類進(jìn)行覆蓋;2)static是不能修飾抽象方法的。靜態(tài)方法占據(jù)固定內(nèi)存空間,而抽象方法根本就不可能運(yùn)行,不會(huì)加載到內(nèi)存中。所以,static關(guān)鍵字不能修飾抽象方法。5.2.2 抽
12、象類抽象類是用關(guān)鍵字abstract修飾的類為抽象類。語(yǔ)法格式形如:abstract class 抽象類名 類體抽象類只是具體實(shí)體的抽象描述,是不可以實(shí)例化對(duì)象。盡管抽象類定義構(gòu)造方法是沒有語(yǔ)法錯(cuò)誤,但是沒有實(shí)際意義。抽象類中可以定義非抽象方法,也可以定義抽象方法。抽象方法在它的派生子類中可以覆蓋,來(lái)實(shí)現(xiàn)具體功能。抽象類派生出的子類,必須對(duì)抽象類中的抽象方法重寫。如果沒有對(duì)抽象方法重寫,該子類須定義為抽象類,否則產(chǎn)生編譯錯(cuò)誤。與抽象方法類似,如果一個(gè)類要定義為抽象類,就不能用關(guān)鍵字static或關(guān)鍵字final修飾,原因同抽象方法,在這里就不再說(shuō)明。例5.2 抽象類的示例。public abs
13、tract class AbstractClassExample /AbstractClassExample.javapublic abstract void showMessage(); /定義抽象方法showMessage()public void printClassName(String name)/定義非抽象方法printClassName(String)System.out.println(name);public class DerivedAbstractClass extends AbstractClassExample/DerivedAbstractClass.javapub
14、lic DerivedAbstractClass()System.out.println(Derived Abstract Class Definition);public void showMessage() /覆蓋父類的showMessage()方法;System.out.println(Derived Abstract Class Message);public static void main(String args)DerivedAbstractClass dac=new DerivedAbstractClass();dac.showMessage();dac.printClassN
15、ame(Class name is: DerivedAbstractClass);/引用繼承來(lái)的方法System.exit(0);圖5-4 例5.2的運(yùn)行結(jié)果5.3 多態(tài)性多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計(jì)的重要特性,它是繼承機(jī)制產(chǎn)生的結(jié)果。所以,繼承是多態(tài)的前提。面向?qū)ο蟪绦蛟O(shè)計(jì)中,嚴(yán)格的來(lái)說(shuō)多態(tài)性是運(yùn)行綁定機(jī)制。這種機(jī)制是實(shí)現(xiàn)將方法名綁定到方法具體實(shí)現(xiàn)代碼。通俗地理解就是“一個(gè)名字,多種形式”。實(shí)際上,最常見的多態(tài)的是符號(hào)“+”,有如下的表示式:6+5 /實(shí)現(xiàn)整數(shù)相加3+5.0f /將3隱性轉(zhuǎn)化為float類型,實(shí)現(xiàn)單精度數(shù)字的相加IAMCHINESE+4 /實(shí)現(xiàn)字符串連接操作。 同一個(gè)“+”有多種
16、含義:整數(shù)相加、單精度數(shù)字相加、雙精度數(shù)字相加、字符串連接等操作。當(dāng)然,上述的表達(dá)式3+5.0f中數(shù)據(jù)類型的隱性的轉(zhuǎn)換也是一種多態(tài)的體現(xiàn)。又如,在第三章討論的對(duì)象的finalize()方法也是多態(tài)。因?yàn)?,不同類型的?duì)象都有finalize()方法,但根據(jù)要求的不同,可以賦予finalize()方法不同代碼內(nèi)容,產(chǎn)生不同的功能。另外,類的構(gòu)造方法也是多態(tài)的一種形式。在創(chuàng)建對(duì)象時(shí),根據(jù)參數(shù)的性質(zhì)來(lái)選擇構(gòu)造方法初始化對(duì)象。根據(jù)消息選擇響應(yīng)方法的角度來(lái)看,多態(tài)分成兩種形式:編譯多態(tài)(Compile-time Polymorphism)和運(yùn)行多態(tài)(Run-time Polymorphism)。在編譯時(shí)期
17、根據(jù)信息選擇響應(yīng)的方法稱為編譯多態(tài)。Java語(yǔ)言中,實(shí)現(xiàn)編譯多態(tài)性主要有方法的重載。運(yùn)行的多態(tài)是在程序運(yùn)行的時(shí)才可以確認(rèn)響應(yīng)的方法。通常運(yùn)行的多態(tài)是通過(guò)繼承機(jī)制引起的。從實(shí)際編程的角度來(lái)看,Java語(yǔ)言實(shí)現(xiàn)多態(tài)性有三種形式:1)方法的重載;2)通過(guò)繼承機(jī)制而產(chǎn)生的方法覆蓋;3)通過(guò)接口實(shí)現(xiàn)的方法覆蓋(見5.4.2)。在本節(jié)中對(duì)方法的重載和方法的覆蓋做一個(gè)詳細(xì)的介紹。5.3.1 方法的重載重載(Overloading)實(shí)質(zhì)上就是在一個(gè)類內(nèi)用一個(gè)標(biāo)識(shí)符定義不同的方法或符號(hào)運(yùn)算的方法名或符號(hào)名。Java語(yǔ)言中支持符號(hào)的重載,如前提及的運(yùn)算符“+”。不過(guò)Java語(yǔ)言中不支持用戶自定義的符號(hào)重載,可以支
18、持用戶定義方法的重載。方法的重載具體可以理解為,同一個(gè)方法名對(duì)應(yīng)不同的方法定義。這些方法的格式說(shuō)明中的參數(shù)不同,即,具體涉及到參數(shù)的類型、參數(shù)的個(gè)數(shù)是有所不同的。值得注意的是,在Java語(yǔ)言中,方法的返回值和方法的訪問控制不作為區(qū)分方法的一個(gè)因素。請(qǐng)看下列的方法定義格式:public void showMessage()public void showMessage(int x)/與不同的參數(shù)public void showMessage(int y)/ 與不同的參數(shù)名private void showMessage()/與不同的訪問控制public int showMessage()/與不同
19、的返回值類型在這些表達(dá)式中方法定義和方法定義是可以視為方法的重載。方法定義和方法定義和方法定義不是方法的重載。在編譯時(shí)會(huì)將方法定義、方法定義和方法定義作為同一種方法,如果這三種形式的showMessage()方法放在同一個(gè)類中,會(huì)產(chǎn)生編譯錯(cuò)誤。盡管方法定義和方法定義具有不同的參數(shù)名,但二者是同一個(gè)方法定義,不能視之為重載,因?yàn)閰?shù)個(gè)數(shù)和參數(shù)類型相同。例5.3 Java中方法重載的示例。public class OverloadingExamplepublic OverloadingExample() /無(wú)參構(gòu)造方法System.out.println(方法重載示例:無(wú)參構(gòu)造方法);public
20、 OverloadingExample(String string)/有參構(gòu)造方法System.out.println(方法重載示例:有參構(gòu)造方法,參數(shù):+string);public void showMessage() System.out.println(方法重載的信息顯示);public void showMessage(String string) System.out.println(顯示字符串:+string);public void showMessage(int intValue) System.out.println(顯示整數(shù):+intValue); public void
21、 showMessage(String string,int intValue) System.out.println(顯示字符串:+string);System.out.println(顯示整數(shù):+intValue);public static void main(String args)OverloadingExample ole1=new OverloadingExample();OverloadingExample ole2=new OverloadingExample(對(duì)象2);ole1.showMessage(1);ole1.showMessage(對(duì)象1);ole2.showMe
22、ssage();ole2.showMessage(對(duì)象2);System.exit(0); 圖5-5 例5.3的運(yùn)行結(jié)果例5.3中,構(gòu)造方法OverloadingExample()是重載,因?yàn)樗袃煞N形式:有參和無(wú)參。在主方法main()中,根據(jù)實(shí)參情況不同,由編譯器分別調(diào)用無(wú)參的構(gòu)造方法和有參的構(gòu)造方法,創(chuàng)建的對(duì)象ole1和ole2。對(duì)象ole1和對(duì)象ole2調(diào)用成員方法showMessage()是重載的,根據(jù)調(diào)用的實(shí)際參數(shù)的類型,編譯器自動(dòng)加載不同的showMessage()方法形式。例如,運(yùn)行ole1對(duì)象的showMessage(1),編譯器將showMessage名綁定到方法showM
23、essage(int)定義的代碼中,具體的運(yùn)行結(jié)果觀察圖5-5。在下面通過(guò)一個(gè)實(shí)際問題來(lái)討論重載。例5.4 定義一個(gè)類Counter,具有實(shí)現(xiàn)求絕對(duì)值運(yùn)算的功能。public class Counter public Counter() System.out.println(求絕對(duì)值); public int abs(int x) /整數(shù)求絕對(duì)值 return x=0?x:-x; public long abs(long x) /長(zhǎng)整數(shù)求絕對(duì)值 return x=0?x:-x; public float abs(float x) /單精度求絕對(duì)值 return x=0?x:-x; public
24、 double abs(double x) /雙精度求絕對(duì)值 return x=0?x:-x; public static void main(String args) Counter c=new Counter(); System.out.println(-30.445的絕對(duì)值=+c.abs(-30.445); System.out.println(-30的絕對(duì)值=+c.abs(-30); System.exit(0); 圖5-6 例5.4的運(yùn)行結(jié)果5.3.2 方法的覆蓋和隱藏方法的覆蓋(Overriding)實(shí)質(zhì)是指子類具有重新定義父類成員方法的能力。這種重新定義表示子類定義的方法具有和父
25、類的方法同名稱、同參數(shù)類型、同參數(shù)個(gè)數(shù)、以及同返回值。方法格式定義盡管相同,但具有不同的方法體,實(shí)現(xiàn)的內(nèi)容根據(jù)程序員的要求而有所不同。子類的方法覆蓋父類的同名方法。這意味著,子類對(duì)象的實(shí)例方法調(diào)用只會(huì)調(diào)用子類中定義的方法,而不是父類中同格式說(shuō)明的方法。從第4章介紹可以知道,類的靜態(tài)方法是一種類方法,對(duì)該類的所有對(duì)象是共享的。有一種特殊的情況,就是子類覆蓋了父類內(nèi)定義的靜態(tài)方法。這時(shí),父類的靜態(tài)方法被隱藏起來(lái)了,在子類中失去作用。要求子類定義的方法必須和父類的靜態(tài)方法具有相同性質(zhì)和相同的方法格式說(shuō)明。即,同為靜態(tài)類型、同方法名、同方法參數(shù)類型、同方法參數(shù)個(gè)數(shù)、同返回值。如果子類定義的方法在重新定
26、義父類的靜態(tài)方法時(shí),沒有用關(guān)鍵字static定義,則會(huì)產(chǎn)生錯(cuò)誤。因?yàn)?,用一句話可以概括成:如果子類的方法覆蓋父類的靜態(tài)方法,則父類的方法在子類中隱藏起來(lái)了。為了說(shuō)明覆蓋的定義,請(qǐng)看例5.5。例5.5 方法覆蓋和隱藏的示例。public class ParentClass /ParentClass.java public static String getMessage() /ParentClass類方法getMessage();return 獲取ParentClass類的對(duì)象的信息; public void showMessage(String message) /被ChildClass的sh
27、owMessage()方法隱藏System.out.println(輸出ParentClass類的對(duì)象的信息:+message); public class ChildClass extends ParentClass /ChildClass.java public static String getMessage() /定義ChildClass類方法getMessage(); return 獲取ChildClass類的對(duì)象的信息; public void showMessage(String message) /覆蓋了ParentClass的showMessage()方法。 System.o
28、ut.println(輸出ChildClass類的對(duì)象的信息:+message); public class OverridingTest /定義測(cè)試類OverridingTestpublic static void main(String args)ParentClass cc=new ChildClass(); /對(duì)象變量cc引用ChildClass的對(duì)象System.out.println(輸出一個(gè)對(duì)象);cc.showMessage(Writen by Chen); /調(diào)用對(duì)象cc的方法showMessage() System.out.println(cc.getMessage();
29、/輸出對(duì)象cc的獲取信息 System.out.println(輸出另外一個(gè)對(duì)象); cc=new ParentClass(); /對(duì)象變量cc引用ParentClass類的對(duì)象 cc.showMessage(Writen by Chen); System.out.println(cc.getMessage(); System.out.println(再輸出一個(gè)ChildClass的對(duì)象); ChildClass cc2=new ChildClass(); /創(chuàng)建對(duì)象cc2 cc2.showMessage(Writen by Chen); System.out.println(cc2.getM
30、essage(); System.exit(0);圖5-7 圖5.5的運(yùn)行結(jié)果從圖5-7中顯示的運(yùn)行結(jié)果可以觀察到兩方面的內(nèi)容。首先,子類ChildClass的showMessage()方法覆蓋了父類ParentClass的同名方法。在子類ChildClass中定義getMessage()覆蓋了父類的類方法getMessage(),而父類的類方法getMessage()在子類中隱藏,沒有發(fā)揮作用。如果在子類定義方法getMesssage()中沒有用關(guān)鍵字static修飾,這時(shí)會(huì)產(chǎn)生編譯錯(cuò)誤。其次,在上例中,對(duì)象變量cc聲明為ParentClass的對(duì)象,但是該對(duì)象變量即可引用ParentCla
31、ss的對(duì)象,也可以引用ChildClass對(duì)象。具體引用對(duì)象的類型,取決于在運(yùn)行期間該對(duì)象變量引用的對(duì)象的類型,這就是運(yùn)行時(shí)的多態(tài)。子類覆蓋父類的方法,訪問控制可以不同。但是,子類的訪問控制的訪問權(quán)限不能低于父類的同名方法訪問權(quán)限。否則,會(huì)產(chǎn)生編譯錯(cuò)誤。例如,將例5.5中的ParentClass.java和ChildClass.java改成如下形式:public class ParentClass public static String getMessage() return Hello, Parent Class; protected void showMessage(String mes
32、sage) /保護(hù)類型 System.out.println(Parent Class Message +message); public class ChildClass extends ParentClass private static String getMessage() /定義私有類型,出現(xiàn)編譯錯(cuò)誤,要修改成public則正確。 return Hello Child Class; public void showMessage(String message)/正確 System.out.println(Child Class Message +message); 從編譯上述程序,子
33、類覆蓋父類方法protected static String getMessage(),出現(xiàn)編譯錯(cuò)誤,要修改成protected或public則正確。5.3.3 數(shù)據(jù)成員的隱藏父類的數(shù)據(jù)成員可以在子類中隱藏,只要子類中定義了同名的數(shù)據(jù)成員。即使數(shù)據(jù)成員的類型不同,也視為父類的數(shù)據(jù)成員被隱藏了。如果要在子類中引用父類的同名數(shù)據(jù)成員,只能通過(guò)關(guān)鍵字super(見5.3.4)來(lái)實(shí)現(xiàn)。例5.6 數(shù)據(jù)成員隱藏的示例。public class ParentClass /ParentClass.java public String string; /定義string為Stringpublic ParentC
34、lass() string=Parent Class; System.out.println(Parent Class Definition: +string); protected static String getMessage() return Hello, Parent Class; protected void showMessage(String message) System.out.println(Parent Class Message +message); public class ChildClass extends ParentClass /ChildClass.jav
35、a public int string; /定義string為intpublic ChildClass() string=0; System.out.println(Child Class Definition: +string); protected static String getMessage() return Hello Child Class; public void showMessage(String message) System.out.println(Child Class Message +message); public class OverridingTest /O
36、verridingTest.java public static void main(String args) ChildClass cc=new ChildClass(); cc.showMessage(Writen by Chen); System.out.println(cc.getMessage(); System.exit(0); 圖5-8例5.6的運(yùn)行結(jié)果5.3.4 super關(guān)鍵字super關(guān)鍵字表示對(duì)類的父類的引用。在子類中有時(shí)會(huì)使用父類的數(shù)據(jù)和方法,這時(shí)就可以利用super關(guān)鍵字來(lái)實(shí)現(xiàn)對(duì)父類的引用。super關(guān)鍵字不是一個(gè)對(duì)象的引用,而是調(diào)用父類的成員特有的關(guān)鍵字。super
37、關(guān)鍵字主要應(yīng)用在兩個(gè)方面:1)應(yīng)用于引用父類的構(gòu)造方法;2)應(yīng)用于引用父類中被子類覆蓋的成員方法和隱藏?cái)?shù)據(jù)成員。例5.7 super關(guān)鍵字的示例。public class SuperClass /SuperClass.javaprivate String string;private int intValue;public SuperClass() /構(gòu)造方法string=Super Class;intValue=1;public void setIntValue(int x)intValue=x;public void setStringValue(String string)this.st
38、ring=string;public int getIntValue()return intValue;public String getStringValue()return string;public void showMessage()System.out.println(父類的信息有:+string+,+intValue);public class SubClass extends SuperClass /SubClass.javapublic String string;public int intValue;public char subChar;public SubClass()
39、super(); /引用父類的構(gòu)造方法subChar=C;public void setChar(char c)subChar=c;public char getChar()return subChar;public void showMessage()super.showMessage(); /引用父類的被覆蓋的方法showMessage()System.out.println(子類增加信息:+subChar);public class SuperTest /SuperTest.javapublic static void main(String args) SubClass sc=new
40、SubClass(); /創(chuàng)建對(duì)象sc sc.showMessage(); /調(diào)用方法showMessage() System.exit(0);圖5-9 例5.7的運(yùn)行結(jié)果值得注意的是,父類的私有數(shù)據(jù)成員不能通過(guò)super關(guān)鍵字來(lái)訪問。因?yàn)楦割惖乃接袛?shù)據(jù)成員的作用域只在定義類中有效。所以,在SubClass.java中試圖通過(guò)super.string來(lái)訪問父類定義的數(shù)據(jù)string,會(huì)產(chǎn)生編譯錯(cuò)誤。另外,不能通過(guò)super關(guān)鍵字在子類對(duì)象中引用父類靜態(tài)成員。因?yàn)?,類定義的靜態(tài)成員方法和靜態(tài)數(shù)據(jù)成員被加載后會(huì)占據(jù)固定的存儲(chǔ)空間,對(duì)所有類的對(duì)象有效。子類靜態(tài)成員占據(jù)的空間與父類靜態(tài)成員占據(jù)的空間沒
41、有關(guān)系。如果在子類引用父類的靜態(tài)類方法和靜態(tài)數(shù)據(jù)成員會(huì)產(chǎn)生編譯錯(cuò)誤。把例5.7改寫成如下形式后SubClass.java會(huì)出現(xiàn)編譯錯(cuò)誤。public class SuperClass private static String string; /定義靜態(tài)數(shù)據(jù)string private static int intValue; /定義靜態(tài)數(shù)據(jù)int public SuperClass() string=Super Class; intValue=1; public void setIntValue(int x) intValue=x; public void setStringValue(St
42、ring string) this.string=string; public int getIntValue() return intValue; public String getStringValue() return string; public static void showMessage() /定義靜態(tài)成員方法 System.out.println(父類的信息有:+string+,+intValue); public class SubClass extends SuperClass public static String string; public static int i
43、ntValue; public char subChar; public SubClass() super(); subChar=C; public void setChar(char c) subChar=c; public char getChar() return subChar; public static void showMessage() super.showMessage(); /編譯錯(cuò)誤 System.out.println(子類增加信息:+subChar); 5.4 接口Java語(yǔ)言不支持多繼承,但是在有的情況下需要使用多繼承。比如大學(xué)的人員分成學(xué)生和在校的職工。如果某些在
44、校職工正在讀本校的在職研究生,這時(shí)他們就具有在校職工和學(xué)生兩種身份。用UML簡(jiǎn)圖來(lái)表示,如圖5-10所示,其中,用Person表示人,用Student表示學(xué)生,用Employee表示職工,用EmployedStudent表示在讀的本校職工。在現(xiàn)實(shí)生活中類似的多繼承的例子隨處可見。EmployeeEmployedStudentStudentPerson圖5-10 UML簡(jiǎn)圖表示多繼承可是,多繼承的存在有可能導(dǎo)致“二義性問題”。假設(shè)Person類具有某個(gè)公共方法如setName(),那么類Employee和類Student都繼承了該公共方法,在這兩個(gè)類中通過(guò)覆蓋可以重寫該方法setName(),當(dāng)
45、在類EmployedStudent的對(duì)象中調(diào)用實(shí)例方法setName()時(shí),將無(wú)法判別調(diào)用的是從類Employee繼承而來(lái)的方法,還是從類Student中繼承的方法,具體的調(diào)用完全取決于運(yùn)行狀態(tài)。這種“二義性問題”會(huì)導(dǎo)致用戶對(duì)程序代碼的錯(cuò)誤的理解。Java語(yǔ)言可以通過(guò)接口概念,一方面實(shí)現(xiàn)多繼承,同時(shí)避免“二義性問題”的產(chǎn)生,另一方面為Java語(yǔ)言在支持單繼承機(jī)制的前提下實(shí)現(xiàn)多態(tài)提供了方便。所謂的接口(Interface)實(shí)質(zhì)上就是為外界提供運(yùn)算,而不揭示這些運(yùn)算的結(jié)構(gòu)或具體的實(shí)現(xiàn)內(nèi)容。從編程的角度看,Java語(yǔ)言定義的接口實(shí)際上是一組抽象方法和常量的集合,為其他類提供運(yùn)算的外部說(shuō)明。接口為一個(gè)
46、或多個(gè)類提供一個(gè)行為規(guī)范,具體的實(shí)現(xiàn)在這些類中完成,這些類之間并不存在層次關(guān)系。通過(guò)接口可以了解對(duì)象的實(shí)例方法的原型,而不需要了解這些方法的具體實(shí)現(xiàn)。接口的存在有效解決了如何實(shí)現(xiàn)多繼承,同時(shí)避免了由于多繼承產(chǎn)生的“二義性問題”。5.4.1 接口的格式定義Java語(yǔ)言中,接口是通過(guò)關(guān)鍵字interface來(lái)實(shí)現(xiàn)定義的,具體格式如下:public interface 接口名 extends 父接口名表 接口體接口名的定義規(guī)則同類名的規(guī)則。接口名可以由多個(gè)單詞組成,每個(gè)單詞的首字母為大寫。接口可以有繼承關(guān)系,通過(guò)關(guān)鍵字extends實(shí)現(xiàn)繼承。接口體中定義的是方法和常量。接口體中定義的所有方法不管是否
47、用來(lái)顯式的定義為公共的抽象性質(zhì)(public abstract),還是缺省性質(zhì)定義,所有方法隱含為公共的(public)和抽象(abstract)的,方法體為空。接口體中定義的常量格式如下:final static數(shù)據(jù)類型 常量標(biāo)識(shí)符=常量值; 例5.8 接口的示例。/Movable.javainterface Movable /定義接口Movable public abstract void move();/Drawable.javainterface Drawable /定義接口Drawable public abstract void draw();/Shapable.javainter
48、face Shapable extends Movable,Drawable /繼承了Movable和Drawable接口; public abstract void run();在例5.8中定義了三個(gè)接口:Movable、Drawable和Shapable,接口Shapable繼承了接口Movable和接口Drawable,這意味著接口Shapable繼承接口Movable的抽象方法move()和繼承了接口Drawable的抽象方法draw()。5.4.2 接口的實(shí)現(xiàn)Java語(yǔ)言中通過(guò)關(guān)鍵字implements來(lái)實(shí)現(xiàn)接口,具體的實(shí)現(xiàn)是通過(guò)類來(lái)完成的。接口實(shí)現(xiàn)的具體格式如下:class 類名
49、implements 接口名表 類體 接口的定義類似于抽象類,但是它的實(shí)現(xiàn)是依賴于類,不是通過(guò)繼承來(lái)實(shí)現(xiàn)的。在實(shí)現(xiàn)的類中,對(duì)接口中定義的所有方法進(jìn)行覆蓋,根據(jù)具體要求進(jìn)行定義。如果沒有對(duì)所有方法覆蓋,會(huì)導(dǎo)致實(shí)現(xiàn)接口的類編譯錯(cuò)誤,或必須定義該類為抽象類。例5.9 定義一個(gè)長(zhǎng)方形的類RectangleShape實(shí)現(xiàn)例5.8定義的接口Movable和Drawable的示例。public class RectangleShape implements Movable,Drawable public void move() System.out.println(Rectangle Move); publ
50、ic void draw() System.out.println(Draw a Rectangle); public static void main(String args) RectangleShape rs=new RectangleShape(); rs.move(); rs.draw(); System.exit(0); 圖5-11 例5.9的運(yùn)行結(jié)果例5.10 定義一個(gè)立方體的類CubeShape實(shí)現(xiàn)例5.8定義的接口Movable和Drawable的示例。public class CubeShape extends RectangleShape /CubeShape.java
51、public void move() System.out.println(Cube Move); public void draw() System.out.println(Draw a Cube); public static void main(String args) RectangleShape cs=new CubeShape(); /定義對(duì)象變量cs,引用CubeShape對(duì)象 cs.move(); cs.draw(); System.exit(0); 圖5-12 例5.10的運(yùn)行結(jié)果例5.9和例5.10定義的類CubeShape是類RectangleShape的子類,所以也實(shí)現(xiàn)了接口Movable和接口Drawable。對(duì)這兩個(gè)接口中的方法move()和方法draw()進(jìn)行覆蓋,使得類RectangleShape和類CubeShape的對(duì)象對(duì)同一種方法名具有不同的實(shí)現(xiàn)內(nèi)容。在例5.10中,一個(gè)RectangleShape對(duì)象變量cs可以引用RectangleShape對(duì)象,也可
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度新型能源汽車短期借用協(xié)議書4篇
- 2025年度文化產(chǎn)業(yè)發(fā)展基金投資合作合同4篇
- 2025年度智能家居櫥柜定制工程協(xié)議書4篇
- 2025年度新能源車輛租賃代理合同模板3篇
- 2024版離婚協(xié)議年范本
- 2025年單梁橋式起重機(jī)項(xiàng)目可行性研究報(bào)告-20250102-152444
- 2025年中鹽青海昆侖堿業(yè)有限公司招聘筆試參考題庫(kù)含答案解析
- 2025年四川壯禾人力資源有限公司招聘筆試參考題庫(kù)含答案解析
- 2025年中國(guó)郵政證券有限責(zé)任公司招聘筆試參考題庫(kù)含答案解析
- 2025年江蘇弘景建設(shè)規(guī)劃有限公司招聘筆試參考題庫(kù)含答案解析
- 漆畫漆藝 第三章
- CB/T 615-1995船底吸入格柵
- 光伏逆變器一課件
- 貨物供應(yīng)、運(yùn)輸、包裝說(shuō)明方案
- (完整版)英語(yǔ)高頻詞匯800詞
- 《基礎(chǔ)馬來(lái)語(yǔ)》課程標(biāo)準(zhǔn)(高職)
- IEC61850研討交流之四-服務(wù)影射
- 《兒科學(xué)》新生兒窒息課件
- 材料力學(xué)壓桿穩(wěn)定
- 人教版小升初英語(yǔ)知識(shí)點(diǎn)匯總
- 靜態(tài)爆破專項(xiàng)施工方案
評(píng)論
0/150
提交評(píng)論