第五章 類的繼承和super的使用呼叫父類構造方法
類的繼承
mammals |
dogs |
cats |
humans |
lions |
tigers |
leopards |
人是哺乳動物,因為人都具有哺乳動物的所有特徵,但哺乳動物卻不一定是人。哺乳動物類和人類之間就存在繼承關係(IS-A)
繼承是面向物件三大特徵之一,也是實現軟體複用的重要手段。
¯ 繼承的特點
µ 通過繼承,在已有型別基礎之上進行擴充或改造,得到新的資料型別。
ü 已有的型別稱為父類或超類。
ü 得到的新資料型別,稱為子類或派生類
ü 類的繼承提高了程式程式碼的重用性和可擴充性,縮短了軟體開發的週期。
µ 繼承的分類
單繼承---------子類只能有一個直接父類
多重繼承------子類可以有多個直接父類
Java不支援多重繼承 |
類A |
類B |
類C |
類A |
類B |
µ 子類繼承父類的語法格式
[修飾符] class 子類名 extends 父類名{
//子類程式碼部分
}
例5.1 編寫程式示範子類繼承父類的特點。
public class Animal{
public double weight;
public void eat(){
System.out.println("
}
}
public class Dog extends Animal{
public void say(){
System.out.pringln(“狗叫:汪汪汪”);
}
public static void main(String[] args) {
Dog d= new Dog();
d.weight = 150;
d.eat();
d.say();
}
}
¯ 重寫父類的方法
子類擴充套件父類--總是以父類為基礎,額外增加新的屬性和方法。但有一種情況例外:子類需要重寫父類的方法。
例5.2 子類重寫父類的方法
public class Bird{
public void fly(){
System.out.println("我在飛");
}
}
public class Ostrich extends Bird{
//重寫Bird類的fly方法----方法覆蓋(override)
public void fly(){
System.out.println("我只能在地上奔跑");
}
public static void main(String[] args){
Ostrich os = new Ostrich();
os.fly(); //呼叫的是Bird的fly還是Ostrich的fly?
}
}
µ 方法重寫時要遵循的規則:“ 三同一小一大”規則
ü “兩同”即方法名相同,形參列表相同;
ü “一小”指的是子類方法返回值型別應比父類方法返回值型別更小或相等,子類方法宣告丟擲的異常類應比父類方法宣告丟擲的異常類更小或相等;
ü “一大”指的子類方法的訪問許可權應比父類方法更大或相等;
ü 覆蓋方法和被覆蓋方法要麼都是類方法,要麼都是例項方法,不能一個是類方法,一個是例項方法。
µ 方法重寫和方法過載的區別
ü 覆蓋是子類和父類之間的關係;而過載是同一類內部多個方法之間的關係。
ü 覆蓋一般是兩個方法間的,而過載可能有多個過載的方法。
ü 覆蓋的方法有相同的方法名和形參表;而過載的方法只能有相同的方法名,不能有相同的形參表。
ü 覆蓋時根據呼叫它的物件來區分方法;而過載是根據形參表來決定呼叫的是哪個方法。
µ 父類例項的super引用
如果需要在子類方法中呼叫父類被覆蓋的例項方法,可以用super作為呼叫者來呼叫父類被覆蓋的例項方法。
public class Ostrich extends Bird{
… … //子類中原有的內容
public void callOverridedMethod(){
super.fly(); //輸出“我在飛”
}
… …
}
注意:
ü super是Java提供的一個關鍵字,它是直接父類物件的預設引用。
ü 正如this不能出現在static修飾的方法中一樣,super也不能出現在static的方法中
ü 如果子類定義了和父類同名的屬性,也會發生子類屬性覆蓋父類屬性的情形。子類的方法直接訪問該屬性時,都會訪問到覆蓋屬性,無法訪問父類被覆蓋的屬性---通過super來訪問父類被覆蓋的屬性
例5.3 子類屬性覆蓋父類屬性的例項。
如果我們在某個方法中訪問名為a的屬性,但沒有顯示指定呼叫者,系統查詢a的順序為: ü 查詢該方法中是否有名為a的區域性變數 ü 查詢當前類中是否包含名為a的屬性 ü 查詢a 的直接父類中是否包含名為a的屬性,依次上溯a的父類,直到java.lang.Object類,如果最終不能找到名為a的屬性,則系統出現編譯錯誤。 |
¯ 呼叫父類構造方法
子類不會繼承父類的構造方法,但有的時候子類構造方法裡需要呼叫父類構造方法的初始化程式碼。
例寫出下面程式的執行結果。
class Base{
protected double size;
public Base(){
size=0; System.out.println(“Base類無參構造”);
}
public Base(double s){
size=s;System.out.println(“Base類有參構造”);
}
}
public class Sub extends Base{
private String color;
public Sub(){
color=“blue”;System.out.println(“Sub類無參構造”);
}
public Sub(String c){
color=c;System.out.println(“Sub類有參構造”);
}
public static void main(String[] args){
Sub s1=new Sub(); Sub s2=new Sub(“red”);
}
}
要在子類中顯式呼叫直接父類帶引數的構造方法,可通過super()呼叫來實現。例如,
public Sub(double s,String c){
super(s); //呼叫Base類中帶一個引數的構造方法
color=c;
System.out.println(“Sub類有參構造”);
}
注意:super呼叫和this呼叫很像,區別在於super呼叫的是其父類的構造方法,而this呼叫的是同一個類中過載的構造方法。因此,使用super呼叫父類構造也必須出現在子類構造執行體的第一行,所以this呼叫和super呼叫不會同時出現。 |
子類構造方法呼叫父類構造方法分如下幾種情況:
µ 子類構造方法執行體的第一行程式碼使用super顯示呼叫父類構造方法,系統將根據super呼叫裡傳入的實參列表呼叫父類對應的構造方法。
µ 子類構造方法執行體的第一行程式碼使用this顯示呼叫本類中過載的構造方法,系統將根據this呼叫裡傳入的實參列表呼叫本類另一個構造方法。執行本類中另一個構造方法時即會呼叫父類的構造方法。
µ 子類構造方法執行體中既沒有super呼叫,也沒有this呼叫,系統將會在執行子類構造方法之前,隱式呼叫父類無引數的構造方法。
例5.5 構造方法的呼叫順序。