1. 程式人生 > 其它 >Java核心知識之介面、繼承和多型-繼承講解

Java核心知識之介面、繼承和多型-繼承講解

  一、類的繼承

  繼承在面向物件開發思想中是一個非常重要的概念,它使整個程式架構具有一定的彈性,在程式中複用一些已經定義完善的類不僅可以減少軟體開發週期,也可以提高軟體的可維護性和可擴充套件性。

  繼承的基本思想是基於某個父類的擴充套件,指定出一個新的子類,子類可以繼承父類原有的屬性和方法,也可以增加父類所不具備的屬性和方法,或者直接重寫父類中的某些方法。例如:平行四邊形是特殊的四邊形,可以說平行四邊形類繼承了四邊形,這時平行四邊形類將所有四邊形具有的屬性和方法都保留下來,並基於四邊形類擴充套件了一些新的平行四邊形特有的屬性和方法。

  eg :分別建立 Test1 類和 Test2 類,在 Test1 類中編寫成員方法 doSomething() 和 doIt() ,使 Test2 類繼承 Test1 類,重寫父類的這兩個方法和構造方法,並新增 doSomethingnew() 方法。其他 Test2 類的構造方法中使用 super 關鍵字呼叫父類的構造方法和成員方法等。

  class Test1 {

  public Test1(){ //構造方法

  System.out.println("Test1.Test1()");

  }

  protected void doSomething() { //成員方法

  System.out.println("Test1.doSomething()");

  }

  protected Test1 doIt() { //方法返回值型別為 Test1 型別

  System.out.println("Test1.doIt()");

  return new Test1();

  }

  }

  class Test2 extends Test1{ //繼承父類

  public Test2 () { //構造方法

  super(); //呼叫父類的構造方法

  super.doSomething(); //呼叫父類成員方法

  System.out.println("Test2.Test2()");

  }

  public void doSomethingnew() { //新增方法

  System.out.println("Test2.doSomethingnew()");

  }

  public void doSomething() { //重寫父類方法

  System.out.println("Test2.doSomething()");

  }

  public Test2 doIt() { //重寫父類方法,方法返回值型別為 Test2 型別

  System.out.println("Test2.doIt()");

  return new Test2();

  }

  }

  定義了兩個類,其他 Test2 類繼承 Test1 類,可以說 Test1 類為 Test2 類的父類, Test2 類為 Test1 類的子類。在子類中可以連通初始化父類構造方法來完成子類初始化操作,既可以在子類的構造方法中使用 super() 語句呼叫父類的構造方法,也可以在子類中使用 super 關鍵字呼叫父類的成員方法等,但是子類沒有許可權呼叫父類中被修飾為 private 的方法,只可以呼叫父類中修飾為 public 或 protected 的成員方法,例如,子類構造方法中可以使用 super 關鍵字呼叫父類的 doSomething 方法,因為 doSomething() 方法的許可權修飾符為 protected 。 同時在子類中也可以定義一些新方法,如子類中的 doSomethingnew() 方法。

  繼承並不只是擴充套件父類的功能,還可以重寫父類的成員方法。重寫(換可以稱為覆蓋)就是在子類中將父類的成員方法的名稱保留,重寫成員方法的實現內容,更改成員方法的儲存許可權,或是修改成員方法的返回值型別。例如,子類中的 doSomething|() 方法,除了重寫方法的實現內容之外,還將方法的修飾許可權修改為 public 。

  在繼承中還有一種特殊的重寫方式,子類與父類的成員方法返回值、方法名稱、引數型別即個數完全相同,唯一不同的是方法實現內容,這種特殊重寫方式被稱為重構。

  當重寫父類方法時,修改方法的修飾許可權只能從小的範圍到大的範圍改變,例如父類中的 doSomethin() 方法的修飾許可權為 protected ,繼承後子類中的方法 doSomething() 的修飾許可權只能修改為 public ,不能修改為 private 。

  在 Java 中一切都以物件的形式處理,在繼承的機制中,建立一個子類物件,將包含一個父類子物件,這個物件與父類建立的物件一樣。兩者的區別在與後者來自外部,而前者來自子類物件的內部。當例項化子類物件時,父類物件也相應被例項化,換句話說,在例項化子類物件時,Java 編輯器會在子類的構造方法中自動呼叫父類的無參構造方法。

  eg :建立 Subroutine 類和兩個父類,分別為 Parent 和 SubParent 。這 3 個類的繼承關係是 Subroutine 類繼承 SubParent 類,而 SubParent 類繼承 Parent 類。分別在這 3 個類的構造方法中輸出構造方法名稱,然後建立 Subroutine 類的例項物件,繼承機制將使該類的父類物件自動初始化。

  class Parent{//父類

  public Parent() {

  System.out.println("呼叫父類的 parent() 構造方法");

  }

  }

  class SubParent extends Parent{ //繼承 Parent 類

  public SubParent() {

  System.out.println("呼叫子類的 SubParent() 構造方法");

  }

  }

  public class Subroutine extends SubParent{ //繼承 SubParent 類

  public Subroutine() {

  System.out.println("呼叫子類的 Subroutine()構造方法");

  }

  public static void main(String[] args) {

  Subroutine s=new Subroutine(); //例項化子類物件

  }

  }

  執行結果為 :

  呼叫父類的 parent() 構造方法

  呼叫子類的 SubParent() 構造方法

  呼叫子類的 Subroutine()構造方法

  在子類 Subroutine 的主方法中只調用子類的構造方法例項化子類物件,並且在子類構造方法中沒有呼叫父類構造方法的任何語句,但是在例項化子類物件時它相應太哦用了父類的構造方法。在結果中可以看到呼叫構造方法的順序,首先是頂級父類,然後使上一級父類,最後是子類。也就是說例項化子類物件時首先要例項化父類物件,然後再例項化子類物件,所以在子類構造方法訪問父類的構造方法之前,父類已經完成例項化操作。

  在例項化子類物件時,父類無參構造方法將被自動呼叫,但由參構造方法並不能被自動呼叫,只能依賴於 super 關鍵字顯式地呼叫父類的構造方法。

  如果使用 finalize() 方法對物件進行清理,需要確保子類的 finalize() 方法的最後一個動作是呼叫父類的 finalize() 方法,以保證當垃圾回收物件佔用記憶體時,物件的所有部分都能被正常終止。