繼承在Java中是物件導向程式設計的核心概念之一。當物件之間存在”is-a”關係時,就會使用Java繼承。在Java中,繼承是使用extends
關鍵字來實現的。
Java中的繼承
Java中的繼承是通過從其他類繼承來建立類之間的層次結構的方法。
Java中的繼承是遞迴的 – 因此如果Sedan擴展自Car,而Car擴展自Vehicle,那麼Sedan也從Vehicle類繼承而來。Vehicle變成了Car和Sedan的超類。
繼承在Java應用程序中被廣泛使用,例如擴展Exception類來創建一個特定應用程序的Exception類,其中包含更多信息,例如錯誤代碼。例如NullPointerException。
Java繼承示例
Java中的每個類都隱式擴展了java.lang.Object
類。因此,在Java中,Object類位於繼承層次結構的最頂層。
讓我們看一個如何使用簡單示例在Java中實現繼承的例子。
超類:Animal
package com.journaldev.inheritance;
public class Animal {
private boolean vegetarian;
private String eats;
private int noOfLegs;
public Animal(){}
public Animal(boolean veg, String food, int legs){
this.vegetarian = veg;
this.eats = food;
this.noOfLegs = legs;
}
public boolean isVegetarian() {
return vegetarian;
}
public void setVegetarian(boolean vegetarian) {
this.vegetarian = vegetarian;
}
public String getEats() {
return eats;
}
public void setEats(String eats) {
this.eats = eats;
}
public int getNoOfLegs() {
return noOfLegs;
}
public void setNoOfLegs(int noOfLegs) {
this.noOfLegs = noOfLegs;
}
}
動物是這裡的基礎類別。讓我們創建一個從動物類別繼承的貓類別。
子類別:貓
package com.journaldev.inheritance;
public class Cat extends Animal{
private String color;
public Cat(boolean veg, String food, int legs) {
super(veg, food, legs);
this.color="White";
}
public Cat(boolean veg, String food, int legs, String color){
super(veg, food, legs);
this.color=color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
請注意,我們在Java中使用extends
關鍵字來實現繼承。
Java繼承測試程式
讓我們寫一個簡單的測試類別來創建一個貓物件並使用其中的一些方法。
package com.journaldev.inheritance;
public class AnimalInheritanceTest {
public static void main(String[] args) {
Cat cat = new Cat(false, "milk", 4, "black");
System.out.println("Cat is Vegetarian?" + cat.isVegetarian());
System.out.println("Cat eats " + cat.getEats());
System.out.println("Cat has " + cat.getNoOfLegs() + " legs.");
System.out.println("Cat color is " + cat.getColor());
}
}
輸出:
貓類別沒有getEats()
方法,但程序仍然運行,因為它是從動物類別繼承的。
重要注意事項
-
代碼重用是繼承的最重要好處,因為子類別繼承了父類別的變量和方法。
-
父類別的私有成員對子類別不可直接訪問。就像這個例子中,動物變量noOfLegs對貓類別不可訪問,但通過getter和setter方法間接訪問。
-
默認訪問權限的超類成員僅在相同包中時對子類可訪問。
-
超類構造函數不被子類繼承。
-
如果超類沒有默認構造函數,那麼子類也需要定義一個顯式構造函數。否則將拋出編譯時異常。在子類構造函數中,必須呼叫超類構造函數,且應該是子類構造函數中的第一個語句。
-
Java 不支援多重繼承,子類別只能擴展一個類別。動物類別隱含地擴展了 Object 類別,而貓類別擴展了動物類別,但由於 Java 繼承的遞移性,貓類別也同時擴展了 Object 類別。
-
我們可以建立子類別的實例,然後將其賦值給超類別變數,這稱為向上轉型。以下是向上轉型的簡單示例:
Cat c = new Cat(); // 子類別實例 Animal a = c; // 向上轉型,因為貓也是動物
-
當將Superclass的實例分配給Subclass變數時,稱為downcasting。我們需要明確地將其轉換為Subclass。例如;
Cat c = new Cat(); Animal a = c; Cat c1 = (Cat) a; //明確轉型,因為"c"實際上是Cat型別
請注意,即使我們操作不正確,編譯器也不會投訴,這是因為有明確的轉型。以下是其中一些會在運行時拋出
ClassCastException
的情況。Dog d = new Dog(); Animal a = d; Cat c1 = (Cat) a; //運行時的ClassCastException Animal a1 = new Animal(); Cat c2 = (Cat) a1; //ClassCastException,因為a1在運行時實際上是Animal型別
-
我們可以在Subclass中覆蓋Superclass的方法。但是我們應該始終使用@Override注釋注釋覆蓋的方法。編譯器將知道我們正在覆蓋一個方法,如果超類方法發生變化,我們將在編譯時獲得錯誤,而不是在運行時獲得不需要的結果。
-
我們可以使用super關鍵字調用超類方法並訪問超類變量。當子類中有相同名稱的變量/方法但我們想訪問超類變量/方法時,這很方便。在超類和子類中定義構造函數時,我們還必須顯式調用超類構造函數。
-
我們可以使用
instanceof
指令來檢查對象之間的繼承關係,讓我們通過下面的示例來了解這一點。
```
Cat c = new Cat();
Dog d = new Dog();
Animal an = c;
boolean flag = c instanceof Cat; //normal case, returns true
flag = c instanceof Animal; // returns true since c is-an Animal too
flag = an instanceof Cat; //returns true because a is of type Cat at runtime
flag = an instanceof Dog; //returns false for obvious reasons.
```
- 在Java中,我們不能擴展Final類。
- 如果你在程式碼中不會使用 Superclass,也就是說你的 Superclass 只是一個基礎,用來保留可重複使用的程式碼,那麼你可以將它們保留為抽象類別,以避免客戶類別進行不必要的實例化。這也將限制基礎類別的實例創建。
Java 繼承視頻教程
I have recently published two videos on YouTube explaining Inheritance in detail with sample programs, you should watch them below.
你可以從我們的GitHub 存儲庫中查看更多繼承的例子。
參考:Oracle 文檔
Source:
https://www.digitalocean.com/community/tutorials/inheritance-java-example