Java/繼承

維基教科書,自由的教學讀本

作為面向對象的編程語言,Java也提供了類的繼承機制。利用繼承機制,新建的類可以建立在原有類的基礎之上,使用或者重寫原有類的成員方法,訪問原有類的成員變量。我們稱新類為原有類子類,而原有類為新類的父類(superclass)。如果類A是類B的父類,而類B是類C的父類,我們也稱C是A的子類,類C是從類A繼承而來的。在Java中,類的繼承是單一繼承,也就是說,一個子類只能擁有一個父類,一個父類可以有多個子類。所有Java的類均是由java.lang.Object類繼承而來的,所以Object是所有類的祖先類,而除了Object外,所有類必須有一個父類。通過extends關鍵字可以申明一個類是繼承另外一個類而來的,一般形式如下:

類的繼承格式

class 父类 {
}
class 子类 extends 父类 {
}

重寫

如果一個類從它的父類繼承了一個方法,如果這個方法沒有被標記為 final ,就可以對這個方法進行重寫。

重寫的好處是:能夠定義特定於子類類型的行為,這意味着子類能夠基於要求來實現父類的方法。

在面向對象編程中, overriding 意味着去重寫父類已經存在的方法。

示例:

class Animal{
public void move(){
System.out.println("Animals can move");
}
}
class Dog extends Animal{
public void move(){
System.out.println("Dogs can walk and run");
}
}
public class Test{
public static void main(String args[]){
Animal a = new Animal(); 
Animal b = new Dog(); 
a.move();
b.move();
}
}

結果:

Animals can move
Dogs can walk and run

在上面的例子中,你可以看到儘管 b 是 Animal 類型,但它運行了 dog 類的方法。

原因是:在編譯時會檢查引用類型。然而,在運行時,JVM 會判定對象類型到底屬於哪一個對象。因此,在上面的例子中,雖然 Animal 有 move 方法,程序會正常編譯。在運行時,會運行特定對象的方法。

示例:

class Animal{
public void move(){
System.out.println("Animals can move");
}
}
class Dog extends Animal{
public void move(){
System.out.println("Dogs can walk and run");
}
public void bark(){
System.out.println("Dogs can bark");
}
}
public class Test{
public static void main(String args[]){
Animal a = new Animal(); 
Animal b = new Dog(); 
a.move();
b.move();
b.bark();
}
}

這將產生如下結果:

Test.java:30: cannot find symbol symbol : method bark() location: class Animal b.bark();^

這個程序在編譯時將拋出一個錯誤,因為 b 的引用類型 Animal 沒有一個名字叫 bark 的方法。


方法重寫規則

  1. 重寫方法的參數列表應該與原方法完全相同。
  2. 返回值類型應該和原方法的返回值類型一樣或者是它在父類定義時的子類型。
  3. 重寫函數訪問級別限制不能比原函數高。舉個例子:如果父類方法聲明為公有的,那麼子類中的重寫方法不能是私有的或是保護的。
  4. 只有被子類繼承時,方法才能被重寫。
  5. 方法定義為 final,將導致不能被重寫。
  6. 一個方法被定義為 static,將使其不能被重寫,但是可以重新聲明。
  7. 一個方法不能被繼承,那麼也不能被重寫。
  8. 和父類在一個包中的子類能夠重寫任何沒有被聲明為 private 和 final 的父類方法。
  9. 和父類不在同一個包中的子類只能重寫 non-final 方法或被聲明為 public 或 protected 的方法
  10. 一個重寫方法能夠拋出任何運行時異常,不管被重寫方法是否拋出異常。然而重寫方法不應該拋出比被重寫方法聲明的更新更廣泛的已檢查異常。重寫方法能夠拋出比被重寫方法更窄或更少的異常。
  11. 構造函數不能重寫。

方法覆蓋 (Overriding) 和方法重載 (Overloading)[編輯]

Java 中的方法重載發生在同一個類裡面兩個或者是多個方法的方法名相同但是參數不同的情況。與此相對,方法覆蓋是說子類重新定義了父類的方法。方法覆蓋必須有相同的方法名,參數列表和返回類型。覆蓋者可能不會限制它所覆蓋的方法的訪問。

super 關鍵字[編輯]

super是用在子類中,目的是訪問直接父類中被屏蔽的變量或方法。

子類構造方法中要調用父類的構造方法:

super(参数列表)

子類引用父類成員變量:

super.成员变量名

子類成員方法覆蓋了父類成員方法時,也就是子類和父類有完全相同的方法定義(但方法體可以不同):

super.方法名(参数列表)

示例:

class Animal{
public void move(){
System.out.println("Animals can move");
}
}
class Dog extends Animal{
public void move(){
super.move();
System.out.println("Dogs can walk and run");
}
}
public class Test{
public static void main(String args[]){
Animal b = new Dog(); 
b.move(); 
}
}

結果:

Animals can move
Dogs can walk and run

this關鍵字[編輯]

在類的構造方法中,通過this調用另一個構造方法:

this(参数列表)

      

方法參數或者方法中的局部變量和成員變量同名的情況下,成員變量被屏蔽,此時要訪問成員變量則需要用

this.成员变量名

的方式來引用成員變量。當然,在沒有同名的情況下,可以直接用成員變量的名字,可不用this。

在方法中,需要引用當前對象時候。

this

其實這些用法總結都是從對「this是指向對象本身的一個指針」這句話的更深入的理解而來。