Java 學習記錄 29 — Inheritance

張小雄
6 min readJan 26, 2021

--

今天學習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

這樣的話,操作性就變很高,可以看情況決定要怎麼寫

--

--

張小雄
張小雄

Written by 張小雄

記錄成為軟體工程師的過程

No responses yet