與C++不同的是,在Java中,一個類只能直接繼承另一個類,而不允許繼承多個類,這個新類稱為繼承類、派生類或者子類,而被繼承的類稱為基類或者父類。
繼承類能夠繼承基類的群不屬性和行為。
面向對象程序設計的三大特點為:封裝、繼承和多態。
類的繼承能夠重復呢利用已有的類,在已有類的基礎上進行必要的擴充和修改就可以得到具有新功能和用途的類,從而簡化程序設計,提高了軟件開發的重用性、可維護性和可靠性。
具體格式為:
<修飾詞>class <派生類名> extends <父類名>
{<派生類成員表>
}
習慣要求派生類名第一個字母要大寫。
派生類成員可以是對已有成員的重新定義,賦予新的含義和功能,也可以定義基類中不存在的成員。
Java不支持多重繼承,因此繼承結構為樹狀結構,樹的最頂端額為java.lang.Object
在Object類中提供了許多的成員函數,其中主要的兩個為:
public boolean equals(Object obj)
如果調用對象等于參數對象時返回真。public String toString
返回一個描述調用對象字符串
對于派生類來講,如果沒有顯式的定義構造函數在,則系統將定義一個缺省的構造函數,函數體首先使用super()
語句來調用基類的無參數構造函數,對基類成員變量進行初始化,然后再調用派生類的無參數構造函數進行初始化。
在派生類中也能顯示的定義構造函數,加上super()語句,實現對基類數據成員初始化的任務。
這里補充一下super的含義:super代表了父類,我們可以通過super來調用父類的構造函數,成員函數和成員變量。在一般情況下子類繼承了父類的所有屬性,因此一般情況下我們都不需要使用super,但是當子類的成員和父類發生沖突或者涉及到子類的構造函數的時候就會用到super。
當子類的成員和父類的成員重復的時候子類的成員會對父類覆蓋,因此想要訪問父類的成員時就必須使用super顯式地調用父類的成員。(包含父類的成員變量和成員方法)。
子類的構造函數系統會默認在開頭加上一句super()
;來訪問父類的無參構造函數,無論我們是否定義了子類的構造函數(如果沒有定義系統會默認定義一個無參構造函數,其中剛開始會運行super()
來運行父類無參構造函數,然后會對子類中特有的變量進行初始化,如果我們定義了子類的構造函數,系統同樣 的會在函數開頭加上一句super()
),這就會導致一個問題就是如果父類沒有無參構造函數就會發生錯誤。
在類中,若定義了構造函數,則系統不會隱含定義無參構造函數。如果定義了一個有參構造函數則訪問其無參構造函數是錯誤的。
如果父類只有有參構造函數我們在子類的構造函數中就不能調用super()
,所以我們必須顯式調用父類的有參構造函數,即super(參數列表);
如果想要了解詳細情況可以移步:傳送門1 | 傳送門2
派生類對基類成員的繼承:若派生類繼承的是不同包中的父類,則只能直接訪問父類中屬于public
和protected
屬性的成員,不能訪問私有和缺省訪問的成員,若派生類繼承的是同一包中的父類,則能夠直接訪問公有、保護和缺省訪問權限的成員,不能訪問私有成員,即私有成員永遠不能被繼承。(體現其封裝性的、隱藏性的特點)
多態:一個方法可以有一個名稱多種形態。多態實現了“接口與實現的分離”,將“是什么”和“怎么做”分離,改善程序的組織框架以及可讀性,提高程序的可擴展性。
在Java中多態有兩種表現形式:
- 重寫(Override)
也稱作覆蓋,指子類通過繼承覆蓋父類中的方法。
重寫規則:
- 參數列表必須完全與被重寫方法相同
- 返回類型必須是被重寫方法返回值的派生類(當然可以相同)(java5及更早版本必須一樣)
- 訪問權限不能比父類中被重寫的方法訪問權限更低。
- 聲明為
final
或者static
的方法不能被重寫,但是聲明為static
的方法可以再次聲明(不太理解) - 重寫的方法能夠拋出任何非強制異常,無論被重寫的方法是否拋出異常,但是重寫方法不能拋出新的 強制性異常,或者比被重寫方法更廣泛的強制性異常。
- 構造方法不能重寫
當需要在子類中調用父類的被重寫方法時,要使用super
關鍵字。
- 重載(Overload)
指在用一個類中可以定義多個同名的方法,只要確定他們的參數個數和類型不同即可。與返回值沒有關系。
在實際程序設計中,我們用父類的引用對象(指針)指向不同的實例化對象(分配到內存),即用父類的引用對象分別指向父類和子類的實例化成員就可以實現多態。
但是需要注意到一點是:只有方法會被覆蓋,屬性(變量)不會被覆蓋!!!
因此如果我們用父類的引用對象指向子類的實例化,那么我們訪問的方法是經過父類中經過子類重寫后(如果沒有重寫就是父類本身)的方法,但是訪問的屬性只能是父類的,而且我們也不能訪問父類沒有的子類特有的方法。
例如:
class Father
{int age;Father() {age=40;} void eat() {System.out.println("爸爸在吃飯");}
}
class Son extends Father
{int age;Son() {age=19;}void eat() {System.out.println("兒子在吃飯");}void play() {System.out.println("兒子在玩SC2");}
}class Main()
{public static void main(String[] args){Father a=new Son();System.out.println("年齡為"+a.age);a.eat();//a.play();}
}
運行結果為
如果想要運行a.play();
時就會出錯。
如果想要了解更多請戳這里