Java繼承

2019-10-16 22:23:22

繼承可以定義為一個類獲取另一個類的屬性(方法和欄位)的過程。 通過使用繼承,可以按層次順序管理資訊。

繼承其他類的屬性的類稱為子類(或派生類),被其它繼承其屬性的類稱為超類(或基礎類別,父類別)。

1. extends關鍵字

extends是用於繼承類屬性的關鍵字。 以下是extends關鍵字的語法。

語法

class Super {
   .....
   .....
}
class Sub extends Super {
   .....
   .....
}

範例程式碼

以下是演示Java繼承的範例。 在此範例中,可以觀察兩個類,即CalculationMyCalculation

使用extends關鍵字,MyCalculation繼承Calculation類的方法:addition()Subtraction()

將以下程式複製並貼上到名為MyCalculation.java 的檔案中。


// 檔案:MyCalculation.java
class Calculation {
    int z;

    public void addition(int x, int y) {
        z = x + y;
        System.out.println("兩個數的和是:" + z);
    }

    public void Subtraction(int x, int y) {
        z = x - y;
        System.out.println("兩個數的差是:" + z);
    }
}

public class MyCalculation extends Calculation {
    public void multiplication(int x, int y) {
        z = x * y;
        System.out.println("兩個數的乘積是:" + z);
    }

    public static void main(String args[]) {
        int a = 20, b = 10;
        MyCalculation demo = new MyCalculation();
        demo.addition(a, b);
        demo.Subtraction(a, b);
        demo.multiplication(a, b);
    }
}

執行上面範例程式碼,得到以下結果:

兩個數的和是:30
兩個數的差是:10
兩個數的乘積是:200

在給定的程式中,當建立MyCalculation類的物件時,會在物件內部建立超類(Calculation)的內容的副本。就可以使用子類的物件,來存取超類的成員。

Java繼承

超類參照變數可以包含子類物件,但是使用該變數只能存取超類的成員,因此要存取兩個類的成員,建議始終為子類建立參照變數。

如果考慮上面的程式,可以範例化下面給出的類。 但是使用超類參照變數(在本例中為cal),無法呼叫方法multiplication(),因為方法multiplication()屬於子類MyCalculation的方法。

註 - 子類從超類繼承所有成員(欄位,方法和巢狀類)。建構函式不是成員,因此它們不能被子類繼承的,但是可以從子類呼叫超類別建構函式。

2. super關鍵字

super關鍵字與this關鍵字類似,以下是使用super關鍵字的注意事項。

  • 如果它們具有相同的名稱,superthis關鍵字用於區分超類的成員和子類的成員。
  • super關鍵字用於從子類呼叫超類建構函式。

區分成員

如果一個類繼承了另一個類的屬性。如果超類的成員具有與子類相同的名稱,要區分這些變數,使用super關鍵字顯示地存取父類別的屬性,如下所示 -

super.variable; // 存取父類別變數
super.method();// 存取父類別方法

範例程式碼

本節提供了一個演示如何使用super關鍵字用法的程式。

在給定的程式中有兩個類,即SubclassSuperclass,它們都有一個名為display()的方法,具有不同的實現,以及一個num變數,具有不同的值。 呼叫兩個類的display()方法並列印兩個類的變數num的值。 在這裡,使用super關鍵字來區分超類和子類的成員。

將程式複製並貼上到名為Subclass.java的檔案中。


// Subclass.java
class Superclass {
    int num = 20;

    // 超類方法
    public void display() {
        System.out.println("這是超類的顯示方法");
    }
}

public class Subclass extends Superclass {
    int num = 10;

    // 子類方法
    public void display() {
        System.out.println("這是子類的顯示方法");
    }

    public void my_method() {
        // 初始化子類
        Subclass sub = new Subclass();

        // 呼叫子類的display()方法
        sub.display();

        // 呼叫父類別的display()方法
        super.display();

        // 列印子類變數num的值
        System.out.println("子類中名為num的變數的值:" + sub.num);

        // 列印父類別變數num的值
        System.out.println("超類中名為num的變數的值:" + super.num);
    }

    public static void main(String args[]) {
        Subclass obj = new Subclass();
        obj.my_method();
    }
}

執行上面範例程式碼,得到以下結果:

這是子類的顯示方法
這是超類的顯示方法
子類中名為num的變數的值:10
超類中名為num的變數的值:20

3. 呼叫超類建構函式

如果一個類繼承另一個類的屬性,則子類自動獲取超類的預設建構函式。 但是如果要呼叫超類的引數化建構函式,則需要使用super關鍵字,如下所示。

super(parm-values);

範例程式碼

下面給出的程式中演示了如何使用super關鍵字來呼叫超類的引數化建構函式。 這個程式包含一個超類和一個子類,超類中包含一個接受整數值的引數化建構函式,在子類中使用super關鍵字來呼叫超類的引數化建構函式。

將以下程式複製並貼上到名為Subclass.java 的檔案中 -

// Subclass.java
class Superclass {
    int age;

    Superclass(int age) {
        this.age = age;
    }

    public void getAge() {
        System.out.println("超類中名為age的變數的值是: " + age);
    }
}

public class Subclass extends Superclass {
    Subclass(int age) {
        super(age);
    }

    public static void main(String argd[]) {
        Subclass s = new Subclass(24);
        s.getAge();
    }
}

執行上面範例程式碼,得到以下結果:

超類中名為age的變數的值是: 24

4. IS-A關係

IS-A是這樣的一種說法:物件A是物件B的一種。下面來看看如何使用extends關鍵字實現繼承。

public class Animal {

}

// Mammal IS-A Animal
public class Mammal extends Animal {

}

// Reptile物件是(IS-A)物件 Animal 的一種
public class Reptile extends Animal {
}

// Dog物件是(IS-A)物件 Mammal 的一種
public class Dog extends Mammal {

}

基於上面的例子,在物件導向的術語中,以下是真的 -

  • 動物(Animal)類是哺乳動物(Mammal)類的超類。
  • 動物(Animal)類是爬行動物(Reptile)類的超類。
  • 哺乳動物(Mammal)類和爬行動物(Reptile)是Animal類的子類。
  • 狗(Dog)是哺乳動物(Mammal)類和動物(Animal)類的子類。

現在,如果使用IS-A關係,可以這樣描述 -

  • Mammal IS-A Animal
  • Reptile IS-A Animal
  • Dog IS-A Mammal
  • 因此: Dog IS-A Animal

通過使用extends關鍵字,子類將能夠繼承超類的所有屬性,但超類的私有屬性除外。可以確保Mammal使用instanceof運算子來判斷它是Animal型別。

範例程式碼


class Animal {
}

class Mammal extends Animal {
}

class Reptile extends Animal {
}

public class Dog extends Mammal {

    public static void main(String args[]) {
        Animal a = new Animal();
        Mammal m = new Mammal();
        Dog d = new Dog();

        System.out.println(m instanceof Animal);
        System.out.println(d instanceof Mammal);
        System.out.println(d instanceof Animal);
    }
}

執行上面範例程式碼,得到以下結果:

true
true
true

通過上面的學習,現在對extends關鍵字應該有很好的理解了,下面來看看implements關鍵字如何用於獲取IS-A 關係。

通常,implements關鍵字與類一起用於繼承介面的屬性。 介面永遠不能被類擴充套件。

範例

public interface Animal {

}

public class Mammal implements Animal {

}

public class Dog extends Mammal {

}

4.1. instanceof關鍵字

使用instanceof運算子來檢查確定Mammal是否是Animal類的一種,Dog是否是Animal類的一種。

範例

interface Animal{}
class Mammal implements Animal{}

public class Dog extends Mammal {

   public static void main(String args[]) {
      Mammal m = new Mammal();
      Dog d = new Dog();

      System.out.println(m instanceof Animal);
      System.out.println(d instanceof Mammal);
      System.out.println(d instanceof Animal);
   }
}

執行上面範例程式碼,得到以下結果:

true
true
true

5. HAS-A關係

這些關係主要基於用法。 這決定了某某類HAS-A是否有某種東西。這種關係有助於減少程式碼重複和錯誤。

範例

public class Vehicle{}
public class Speed{}

public class Van extends Vehicle {
   private Speed sp;
}

上面範例中Vehicle類有HAS-A Speed類。 通過為Speed提供一個單獨的類,不必將屬於Speed類的整個程式碼放在Van類中,這樣就可以在多個應用程式中重用Speed類。

在物件導向的功能中,使用者無需擔心哪個物件正在進行實際工作。要實現這一點,Van類隱藏了使用者的實現細節。 因此,基本上發生的事情是使用者會要求Van類執行某個操作,而Van類要麼自己完成工作要麼要求另一個類執行操作。

6. 繼承的型別

如下所示,有各種各樣型別的繼承。

繼承的類型

需要注意:Java不支援多重繼承。 在Java中,一個類不能擴充套件多個類。 因此以下程式碼是非法的 -

// 非法宣告類
public class extends Animal, Mammal{}

但是,一個類可以實現一個或多個介面,這有助於Java實現多重繼承特性。