今天學習OOP的第二個特性 — Inheritance(繼承)
首先創立一個動物的類
public class Animal { private String sex;
private String size;
private String weight; public Animal(String sex, String size, String weight) {
this.sex = sex;
this.size = size;
this.weight = weight;
} public String getSex() {
return sex;
} public String getSize() {
return size;
} public String getWeight() {
return weight;
} public void eat(){
System.out.println("Animal.eat() method");
}}
可以看到裡面有動物類的
特徵(field):性別sex、尺寸size、重量weight
動作(method):吃eat
接著創立動物下面的狗類
public class Dog extends Animal{ private String tale;
private String fur;
private int eyes;
private int legs; public Dog(String sex, String size, String weight, String tale, String fur, int eyes, int legs) {
super(sex, size, weight);
this.tale = tale;
this.fur = fur;
this.eyes = eyes;
this.legs = legs;
} @Override
public void eat() {
System.out.println("Dog.eat() method");
super.eat();
} public void bark(){
System.out.println("Dog.bark() method");
}
}
第一行 extends Animal 就是繼承於Animal的意思
接著寫contstructor的時候,把想繼承的field放進去
並調用super來告知系統,這些是繼承於Animal的,不是屬於當前Dog類的
狗通用於動物的特徵就繼承,只屬於Dog的特徵就另外寫,
如尾巴長短tale、毛皮長短fur、眼睛數量eyes、腿的數量legs
動作方面也可以繼承動物的吃的動作
並override成 屬於狗的吃法
super.eat()
自然就是指Animal的吃
也能單獨寫屬於狗的動作,如吠叫bark
main.java
public class Main { public static void main(String[] args) { Dog huskies = new Dog("female", "120cm", "20kg", "long", "medium", 2, 4);
huskies.eat();
huskies.bark();
}}
輸出結果:
Dog.eat() method
Animal.eat() method
Dog.bark() method
繼承的好處之一就是減少代碼重複
假如今天要寫 生物 <- 動物 <- 靈長類 <- 人類 <- 台灣人 (箭頭為繼承方向)
可能會是
生物 500個特徵 500個動作
動物 400個特徵 400個動作
靈長類 300個特徵 300個動作
人類 200個特徵 200個動作
台灣人 100個特徵 100個動作
如果沒有繼承這個功能
寫到台灣人之時,前面的特徵與動作就要全部都放進去了
變成
生物 500個特徵 500個動作
動物 500+400個特徵 500+400個動作
靈長類 500+400+300個特徵 500+400+300個動作
人類 500+400+300+200個特徵 500+400+300+200個動作
台灣人 500+400+300+200+100個特徵 500+400+300+200+100個動作
然後哪天要修改的時候,頭直接爆炸,5個類裡有用到的全部都要一起改
修改Dog
這邊要展示quickEat中
使用eat()
跟super.eat()
的差異
public void quickEat(){
System.out.println("Dog.quickEat() method");
eat();
}public void slowEat(){
System.out.println("Dog.slowEat() method");
}@Override
public void eat() {
System.out.println("Dog.eat() method");
slowEat();
super.eat();
}
調用
Dog huskies = new Dog("female", "120cm", "20kg", "long", "medium", 2, 4);
huskies.quickEat();
輸出結果:
Dog.quickEat() method
Dog.eat() method
Dog.slowEat() method
Animal.eat() method
打印完第一行後
進入到第二行
調用了下方的eat()
加上super.eat()
public void quickEat(){
System.out.println("Dog.quickEat() method");
super.eat();
} public void slowEat(){
System.out.println("Dog.slowEat() method");
} @Override
public void eat() {
System.out.println("Dog.eat() method");
slowEat();
super.eat();
}
調用不變
輸出結果:
Dog.quickEat() method
Animal.eat() method
可以看到直接調用了Animal的eat
而不是下方的eat
再來更有趣的,把下方eat註釋掉
還有不用super只用eat
public void quickEat(){
System.out.println("Dog.quickEat() method");
eat();
}public void slowEat(){
System.out.println("Dog.slowEat() method");
}// @Override
// public void eat() {
// System.out.println("Dog.eat() method");
// slowEat();
// super.eat();
// }
調用不變
輸出結果:
Dog.quickEat() method
Animal.eat() method
這個地方就很智能了
就算沒寫super
但因為dog裡面沒有eat了
直接找到Animal裡的eat
這樣的話,操作性就變很高,可以看情況決定要怎麼寫