1. 程式人生 > >Java面向對象編程之繼承(二)

Java面向對象編程之繼承(二)

抽象方法 oid 修飾 屬於 ... 方法的參數 要求 ring 覆蓋

在上一篇博客中,我們已經了解繼承的基本概念和語法,那麽今天我們就來聊一聊有關於繼承的其他東西。

讓我們來了解一下什麽是方法重載(overload)和方法覆蓋(override)

方法重載(overload)

對於類的的方法(包括從父類中繼承的方法),如果有兩個方法的方法名相同,但參數不一致,那麽可以說,一個方法是另一個方法的重載方法。

重載方法必須滿足以下條件:

  • 方法名相同
  • 方法的參數類型、個數、順序至少有一項不相同
  • 方法的返回類型可以不相同
  • 方法的修飾符可以不相同

其中,參數的類型、個數和順序被統稱為參數簽名。來看一下例子:

public class Example{
    public
void amethod(int i ,String s){} //實例方法 // 加入其它方法 public void amethod(int i,String s){} //不可以,因為這個方法和我們定義的實例方法一模一樣,Java虛擬機在執行時不知道該執行哪一個 public void amethod(String s,int i){} //可以,屬於重載方法,參數的順序不一樣 public int amethod(int i,String s){return 0;} //不可以,雖然方法的返回類型不相同,但是方法名和參數簽名完全一致,所以這不能算是重載方法,不能加到Example中
public private amethod(int i,String mystring){} //不可以,方法名和參數簽名相同,所以這也不能算是重載方法 public void Amethod(int i,String s){} //方法名不一樣,是一個新的實例方法,所以可以加入到Example類中 abstract void amethod(int i){} //不可以,該方法的參數數目和已有的不一樣,所以是一種重載方法。但是Example類不是抽象類,所有不能加入這個抽象方法。倘若將Example類改為抽象類。則可以加入這個方法 }

另外,作為程序入口的main()方法也可以被重載。

方法覆蓋(override)

如果子類中定義的一個方法,其名稱、返回類型及參數簽名正好與父類中某個方法的名稱、返回類型及參數簽名相匹配,那麽可以說,子類的方法覆蓋了父類的方法。

覆蓋方法必須滿足多種約束,下面分別介紹:

  1. 子類方法的名稱、參數簽名和返回類型必須與父類方法的名稱、參數簽名和返回類型一致。
  2. 子類方法不能縮小父類方法的訪問權限,這是什麽意思呢?我們可以看下面這個例子:
    public class A extends B{
        private void method(){} //編譯錯誤,子類方法縮小了父類方法的訪問權限
    }
    
    class B{
        public void method(){}
    }

    子類的method()方法是私有的,父類中的method()方法是公有的,子類縮小了父類方法的訪問權限,這是無效的方法覆蓋,會導致編譯錯誤。

  3. 子類方法不能拋出比父類方法更多的異常。子類方法拋出的異常必須和父類方法拋出的異常相同,或者是父類方法拋出的異常的子集。
  4. 方法覆蓋只存在於子類和父類(包括直接父類和間接父類)之間,在同一個類中方法只能被重載,不能被覆蓋。
  5. 父類的靜態方法不能被子類覆蓋為非靜態方法。
  6. 子類可以定義同父類的靜態方法同名的靜態方法,以便在子類中隱藏父類的靜態方法。在編譯時,子類定義的靜態方法也必須滿足和方法覆蓋類似的約束:方法的參數簽名一致,返回類型一致,不能縮小父類方法的訪問權限,不能拋出更多的異常。
  7. 父類的非靜態方法不能被子類覆蓋為靜態方法。
  8. 父類的私有方法不能被子類覆蓋。
  9. 父類的抽象方法可以被子類通過兩種途徑覆蓋:一是子類實現父類的抽象方法;二是子類重新聲明父類的抽象方法。例如以下代碼合法:
abstract class Base(){
    abstract void method1();
    abstract void method2();
}

public abstract class Sub extends Base(){
    public void method1(){...}; //實現method1()方法,並且擴大訪問範圍
    public abstract method2(){}; //重新聲明method2()方法,僅僅擴大訪問權限,但不實現
}

  10.父類的非抽象方法可以被覆蓋為抽象方法。

狹義地理解,覆蓋僅指子類覆蓋父類的具體方法,即非抽象方法,在父類中提供了方法的默認實現方式,而子類采用不同的實現方式。

方法覆蓋與方法重載的異同

方法覆蓋和方法重載具有以下相同點:

  • 都要求方法同名。
  • 都可以用於抽象方法和非抽象方法之間。

方法覆蓋和方法重載具有以下不同點:

  • 方法覆蓋要求參數簽名必須一致,而方法重載要求參數簽名必須不一致。
  • 方法覆蓋要求返回類型必須一致,而方法重載對此不作限制。
  • 方法覆蓋只能用於子類繼承父類的方法,方法重載用於同一個類的所有方法,包括從父類中繼承而來的方法。
  • 方法覆蓋對方法的訪問權限和拋出的異常有特殊的要求,而方法重載在這方面沒有限制。
  • 父類的一個方法只能被子類覆蓋一次,而一個方法在所在的類中可以被重載多次。

Java面向對象編程之繼承(二)