李斌,王睿
(揚州市職業(yè)大學信息工程學院,江蘇揚州225002)
在經(jīng)歷了以大型機為代表的集中計算模式和以PC機為代表的分散計算模式之后,互聯(lián)網(wǎng)的出現(xiàn)使得計算模式進入了網(wǎng)絡計算時代。網(wǎng)絡計算模式的一個特點是計算機是異構(gòu)的,即計算機的類型和操作系統(tǒng)是不一樣的,例如SUN工作站的硬件是SPARC體系,軟件是Unix中的Solaris操作系統(tǒng),而PC機的硬件是Intel體系,操作系統(tǒng)是windows或者是Linux。網(wǎng)絡計算模式的另一個特點是代碼可以通過網(wǎng)絡在各種計算機上進行遷移,這就迫切需要一種跨平臺的編程語言,使得用它編寫的程序能夠在網(wǎng)絡中的各種計算機上能夠正常運行,Java就是在這種需求下應運而生的。Java語言具有簡單、面向?qū)ο?、健壯、安全、可靠、平臺無關性、解釋執(zhí)行、多線程、高性能、易學、適用于網(wǎng)絡等顯著特點,已成為當今最流行的網(wǎng)絡編程語言之一。
Java的所有程序都具有封裝性、繼承性和多態(tài)性。封裝性就是把對象的屬性和服務結(jié)合成一個獨立的相同單位,并盡可能隱蔽對象的內(nèi)部細節(jié);繼承是軟件重用的一種形式,也是自動地實現(xiàn)方法和數(shù)據(jù)共享的機制;多態(tài)性是指在父類中定義的屬性或服務被子類繼承之后,可以具有不同的數(shù)據(jù)類型或表現(xiàn)出不同的行為。本文僅就Java的繼承性進行一定的探討。
繼承是一種由已有類創(chuàng)建新類的機制。繼承也是面向?qū)ο笳Z言的基本要素之一,它是源自類的泛化機制,這種抽象機制提供了一種無限重復利用程序資源的途徑,繼承可以擴展原有的代碼,應用到其他程序中,而不必重新編寫這些代碼,這樣不僅節(jié)省程序開發(fā)時間,而且為未來程序設計增添了新的資源。對象通過繼承,保證了實現(xiàn)部分緊內(nèi)聚和松耦合的良好特性。
利用繼承,我們可以先創(chuàng)建一個共有屬性的一般類,根據(jù)該類再創(chuàng)建具有特殊屬性的新類。在Java語言中,通常我們稱被繼承的一般類為父類(superclass,也叫超類),由繼承而得到的特殊類稱為子類 (subclass)。我們也可以說子類是由父類派生出的類。
Java的繼承原則如下:
1)子類繼承父類的成員變量,包括實例成員變量和類成員變量;
2) 子類繼承父類除構(gòu)造方法以外的成員方法,包括實例成員方法和類成員方法;
3)子類不能繼承父類的構(gòu)造方法,因為父類構(gòu)造方法創(chuàng)建的是父類對象,子類必須聲明自己的構(gòu)造方法,創(chuàng)建子類自己的對象;
4)子類不能刪除父類成員;
5)子類可以增加自己的成員變量和成員方法;
6)子類可以重定義父類成員。
在這段代碼中,子類 SubA繼承了父類SuperA,那么子類自然就擁有了父類的變量a,同時子類自己又添加了自己新的成員變量b以擴充自己的功能。在子類SubA中還可以更改父類SuperA的變量a,讓其適應自己的需求,比如,我們在SubA中增加一行代碼:int a=3;,這樣在子類SubA中的變量a實際上隱藏了父類SuperA的變量a。但是,如果試圖在子類SubA中刪除父類SuperA的變量a,這是Java所不允許的。
子類的對象即是父類的對象。反之不然,父類的對象不是它的子類對象。例如:SuperA supa=new SubA();這條語句是語法允許的,父類對象supa能夠被賦值為子類對象new SubA();而SuBA suba=new SuperA();這條語句編譯是不能通過的,因為子類對象suba是不能能夠被賦值為父類對象new SuperA()的。
子類直接上一層的父類稱為直接父類,如果一個類只有一個直接父類則稱這樣的繼承為單重繼承,一個類也可以是多個直接父類的子類,它從多個父類中繼承了屬性與服務,這樣的繼承稱為多重繼承。
在單重繼承方式下,父類與子類是一對多的關系,一個子類只有一個直接父類,但一個父類可以有多個子類,每個子類又可以作為父類再有自己的子類。
Java只支持單重繼承機制,不支持多重繼承,單重繼承使得Java結(jié)構(gòu)簡單,層次清楚,更安全可靠,從而避免了C++中因多重繼承而引起的難以預測的錯誤。所以聲明的類只能有一個父類。子類的聲明格式為: [<修飾符>]class<子類名>extends<超類名>,從中我們也能清楚看出Java中類的繼承關系為單重繼承關系。在Java中,一個父類可以有多個子類,每個子類又可以作為父類再有自己的子類。由此形成具有樹形結(jié)構(gòu)的層次體系,其中具有繼承關系的、相距多個層次的類之間稱為祖先類和后代類,父類也稱為直接祖先類。這種樹形繼承關系并不違反Java的單重繼承原則。
其實,在Java中,每個類都有父類,如果沒有顯式地標明類的父類,則隱含地假設超類為語言包java.lang中說明的Object類。
在Java中,子類對象對父類成員的訪問權限主要依據(jù)如下規(guī)則進行:
1)子類對父類的私有成員(private)沒有訪問權限;
2)子類對父類的公有成員(public)和保護成員(protected)具有訪問權限;
3)子類對父類中缺省權限成員(default)的訪問分為兩種情況,對同一包中父類的缺省權限成員具有訪問權限,而對不同包中父類的缺省權限成員則沒有訪問權限。
Java只支持單重繼承機制,但是實際應用中有時候也需要使用多重繼承這個功能。
Java中關于接口實現(xiàn)的聲明格式為: [<修飾符>] class<類名> [extends<超類名>] [implements<接口名1>,<接口名2>,…],從中我們可以看出一個類通過關鍵字implements實現(xiàn)了一系列的接口,這實際上就變相地完成了多重繼承的功能,所以通常我們說Java只支持單重繼承,不支持多重繼承,但是卻可以通過接口來實現(xiàn)多重繼承的功能。
問題在于Java中接口本身的繼承關系是單重繼承還是多重繼承呢?我們在學習接口的時候知道,編譯的時候接口會像類一樣被編譯,所以很多人就非常簡單地認為接口既然被當成類編譯,那么自然接口的繼承性也和類一樣是單重的,這也正好和Java的單重繼承原則不謀而合。事實上這樣的理解是完全錯誤的,恰恰相反,接口的本身的繼承性卻是多重的。我們看下面一段程序(程序名為ClassABCTest.java):
程序能正常編譯,運行結(jié)果為(見圖1):
圖1 程序ClassABCTest.java運行結(jié)果
程序中我們聲明了三個接口InterA、InterB、InterC和兩個類 ClassABC、ClassABCTest。接口InterA和InterB是兩個獨立的接口,而接口InterC用關鍵字extends繼承了接口InterA和InterB,事實顯而易見,這是多重繼承關系,即接口InterC同時繼承了接口InterA和InterB。
綜上,Java中類的繼承是單重繼承,但是卻可以通過一個類實現(xiàn)多個接口這種方法來實現(xiàn)多重繼承的功能,或者直接通過一個接口繼承多個接口來實現(xiàn)多重繼承的功能。接口不僅很好地解決了多重繼承,對于單重繼承層次較多、間接父類多的類結(jié)構(gòu),接口還可以避免子類成員的膨脹、龐雜、難以管理等問題,但接口仍然存在不一致性等問題。
即便是運用一個具有較全而完整的繼承機制的語言,實際應遵循的原則也應該是盡可能保持繼承層次體系的簡單性,只有在條件非常充分的情況下才使用多重繼承。
[1]許曉寧.JAVA技術實用教程[M].南京:東南大學出版社,2005.
[2]葉核亞.JAVA2程序設計實用教程(第2版)[M].北京:電子工業(yè)出版社,2007.
[3]布雷恩,等.JAVA2精要語言詳解與編程指南[M].北京:清華大學出版社,2002.
[4]朱喜福.Java程序設計[M].北京:清華大學出版社,2004.
[5]王行言.JAVA語言與面向?qū)ο蟪绦蛟O計[M].北京:清華大學出版社,2000.
[6]劉藝.JAVA程序設計大學教程[M].北京:機械工業(yè)出版社,2006.
[7]Ian Joyner(著).對象揭秘:Java,Eiffel和c++[M].鮑志云(譯).北京:人民郵電出版社,2003.