我們先從生活中的例子開始思考:爲什麼貓和狗都屬於“動物”,而不是單獨定義兩套完全相同的代碼?這時候,“繼承”就派上用場了!繼承的核心思想是子類可以複用父類的屬性和方法,同時擴展自己的功能。想象一下,貓和狗都是動物(父類),它們天生就繼承了“動物”的共同特點(比如會呼吸、會喫飯),同時每個子類又有自己獨特的行爲(比如貓會抓老鼠,狗會看家)。這種“我有的你也有,我有的你還能更好”的關係,就是繼承要解決的問題。
1. 繼承的基本語法:子類 extends 父類¶
要實現繼承,需要先定義一個父類,再用extends關鍵字定義子類,讓子類繼承父類的屬性和方法。
舉個例子:
// 父類:動物(定義共同特徵)
class Animal {
// 父類的屬性(成員變量):動物都有名字和年齡
String name;
int age;
// 父類的方法(成員方法):動物的共同行爲
public void eat() {
System.out.println(name + "正在喫飯");
}
public void sleep() {
System.out.println(name + "正在睡覺");
}
}
// 子類:貓(繼承動物的特徵)
class Cat extends Animal {
// 子類可以添加自己的屬性/方法(貓特有的行爲)
String color; // 貓的顏色
public void catchMouse() {
System.out.println(name + "正在抓老鼠!");
}
}
關鍵點:¶
- 父類(Animal):定義共性特徵(屬性和方法)。
- 子類(Cat):用
extends關鍵字繼承父類,獲得父類的所有非private屬性和方法,並可添加自己的功能。
2. 子類能繼承什麼?不能繼承什麼?¶
子類繼承父類後,會自動獲得:
- 父類的非private屬性(成員變量)。
- 父類的非private方法(成員方法)。
注意:父類中被private修飾的屬性/方法,子類無法直接訪問!如果需要訪問,必須通過父類的public或protected方法(如getter/setter)。
class Animal {
private String name; // 私有屬性,子類無法直接訪問
// 父類提供公共方法訪問私有屬性
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Cat extends Animal {
public void test() {
// 直接訪問父類的name會報錯!必須通過父類的方法
// System.out.println(name); // 錯誤!
System.out.println(getName()); // 正確:通過父類的public方法訪問
}
}
3. 繼承的核心:“is-a”關係¶
繼承不是隨便用的!子類和父類必須是“is-a”關係(子類是父類的一種)。
- ✅ 正確:貓是動物 →
Cat extends Animal(貓“是”動物)。 - ❌ 錯誤:如果關係是“貓有爪子”(has-a關係),應該用組合而非繼承。
比如:
// 正確:學生是人類的一種(is-a)
class Student extends Person {}
// 錯誤:輪子不是交通工具的一種(has-a關係)
// class Wheel extends Vehicle {}
4. 方法重寫(Override):子類“個性化”父類方法¶
子類可以重寫父類的方法,即修改方法的實現邏輯,但保持方法簽名(返回值、參數列表)不變。
例子:父類Animal有一個makeSound()方法,子類Cat和Dog分別重寫這個方法實現不同的叫聲。
class Animal {
public void makeSound() {
System.out.println("動物發出叫聲");
}
}
class Cat extends Animal {
// 重寫父類的makeSound方法
@Override // 註解:告訴編譯器這是方法重寫(可選但建議加)
public void makeSound() {
System.out.println("喵喵喵~");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("汪汪汪!");
}
}
測試:¶
Cat myCat = new Cat();
myCat.makeSound(); // 輸出:喵喵喵~
Dog myDog = new Dog();
myDog.makeSound(); // 輸出:汪汪汪!
5. super關鍵字:調用父類的“我”¶
super是Java關鍵字,用於調用父類的屬性、方法或構造方法。
5.1 調用父類的屬性/方法¶
如果子類和父類有同名屬性/方法,用super明確指定調用父類:
class Animal {
String name = "動物";
public void info() {
System.out.println("我是" + name);
}
}
class Cat extends Animal {
String name = "貓"; // 子類同名屬性
public void showInfo() {
System.out.println("子類name:" + name); // 調用子類屬性
System.out.println("父類name:" + super.name); // 調用父類屬性
}
}
5.2 調用父類的構造方法¶
子類構造方法中,super()必須放在第一行,用於調用父類的構造方法:
class Animal {
String name;
public Animal(String name) { // 父類帶參構造
this.name = name;
}
}
class Cat extends Animal {
public Cat(String name) {
super(name); // 必須先調用父類構造方法
this.name = name;
}
}
6. 繼承的優點和注意事項¶
優點:¶
- 代碼複用:父類定義共性,子類直接繼承,避免重複寫代碼。
- 擴展性:子類可在父類基礎上添加新功能(如
Cat新增catchMouse()方法)。 - 結構清晰:通過繼承形成類的層次關係(如動物→貓→中華田園貓)。
注意事項:¶
- 單繼承:Java類只能單繼承(一個子類只能有一個直接父類),但支持多層繼承(子類的子類)。
- private成員不可直接訪問:父類
private屬性/方法需通過public方法訪問。 - 方法重寫規則:子類方法的返回值類型、參數列表必須與父類完全一致(協變返回值除外,如父類返回Object,子類返回String)。
總結¶
繼承是Java面向對象的核心特性,通過extends關鍵字實現子類繼承父類的屬性和方法。關鍵記住:
- 繼承的核心是“is-a”關係,子類必須是父類的一種。
- 子類可重寫父類方法,通過super調用父類成員。
- 繼承讓代碼更簡潔、複用性更強,是實現代碼擴展和維護的重要手段。
現在你可以嘗試定義自己的父類和子類,比如“人(Person)”作爲父類,“學生(Student)”作爲子類,體驗繼承的魅力吧!