14 分鐘閱讀

物件導向-繼承

TaiwanPhone
User
PhoneNumber
GooleMap()
UberEat()
FB()
Youtube()
Bank(string passWord)
ChinaPhone
PhoneNumber
BaiduMap()
BiliBili()
Bank(string passWord)

業務增加,手機要賣向中國,設計了一個新的大陸手機的類別

然後不幸的是,我們跟中國的電話號碼格式不一樣

想要加入一個方法去處理這個問題,但是要兩邊都加嗎?有一點沒效率又難維護

讓相同的程式反覆出現在不同的類別沒效率又容易出錯,這時候可以時候繼承

Phone類別使用繼承,解決重複問題

TaiwanPhone和ChinaPhone有許多相似的程式碼,因為現實世界也是這樣子,有很多相似的地方

比較一般化的類別,稱為基礎類別。較為特殊化的類別稱為子類別,可以繼承基礎類別

繼承

繼承2

真實世界的行為很複雜

每台手機都可以開機關機,但開機的時地狀況不太一樣,美台手機都會顯示自家廠牌的Logo ,程式碼肯定會與基礎類別不一樣,這個時候子類別就可以改改寫所繼承的程式碼,稱之為 覆寫

繼承3

從基礎類別繼承來的方法,不代表子類別要用同樣的方法去使用它

現實的分組其實更複雜

繼承4

頂層的基礎類別,下面會有一蠍子類別,這些子類別也會有一些子類別繼承他們,這不只可以 避免很多重複的程式碼,也會讓你更好維護與閱讀你的程式

子類別可以為自己擴充

子類別並不是只能繼承來自基礎類別的欄位與方法,也能增加自己的欄位與方法 如IOS有Airdrop功能,不是全部的智能手機都有這個功能

繼承的語法

示範幾個語言的寫法 C# 使用冒號

class SubClass : BaseClass

Python 使用括弧

class SubClass(BaseClass)

Java 使用關鍵字extends

class SubClass extends BaseClass

子類別可以覆寫基礎方法

private方法不能覆寫,若基礎類別有的方法,在子類別也被定義,這兩個方法是互相 不相干的,同名稱也是一樣。

關於類別欄位的部分,只要有同名,基礎類別的欄位會被隱藏起來

列出不同語法的差異

C# 基礎類別使用virtual關鍵字 子類別使用override關鍵字

有一個很酷的東西,當你沒使用virtual或override關鍵字 但是又同名,此時你的方法會被遮蔽,程式就會呼叫基礎類別的方法 並且給出警告,這時候你可以給 new 關鍵字告訴編譯器你就是要遮蔽

class BaseClass{
  public virtual void Go(){
    //code
  }
}
class SubClass : BaseClass{
    public override void Go(){
    //code
  }
}

Java 不需要關鍵字,名稱一樣即可 @Override 註解(annotation) 這是要告訴編譯器你要覆寫,請它幫你檢查有無撰寫錯誤

class BaseClass{
  public void Go(){
    //code
  }
}

class SubClass extends BaseClass{
    @Override
    public void Go(){
    //code
  }
}

Python 不需要關鍵字,名稱一樣即可

class BaseClass:
    def __init__(self) -> None:
        pass
    def Go(self):
        print('Go in Base')  
}
class SubClass(BaseClass):
    def __init__(self) -> None:
        super().__init__()
    def Go(self):
        print('Go in Sub')  
}

子類別可以存取它的基礎類別

覆寫基礎類別後,有時候你還是會想要使用本來的程式碼, 使用每個語言特定的關鍵字你可以存取基礎類別的任何方法

使用這個技巧不只可以少打程式碼,最重要的是你可以改一個地方就好, 如果要兩個地方都改成一樣的程式碼是很容易忘記的

以Java為例子,關鍵字是super

class BaseClass{
    String name = "Base";
    public void Go(){
        System.out.println("Go to train");
    }
}

class SubClass extends BaseClass{
    String name = "Base";
    public void Go(){
        super.Go();
        System.out.println("Go to Taipei");
    }
}

python的關鍵字是super()

C#的關鍵字是base

當基礎類別有建構子時

有繼承關係的話,會先執行基礎類別的建構式然後執行子類別的

C# 強制子類別也要有建構式 語法是 : base(參數,…) 加在建構式語法後面

class BaseClass
{
    public string name;
    public BaseClass(string iname){
        name = iname;
    }
}
class SubClass : BaseClass {
    public SubClass(string iname) : base(iname){
    }
}

python 不強制子類別也要有建構式 語法是原本的語法基礎上加上 super().init(參數)

class BaseClass():
    def __init__(self, name) -> None:
        self.name = name
class SubClass(BaseClass):
    def __init__(self) -> None:
        # super().__init__(name)
        pass

java 強制子類別也要有建構式 語法是 super(參數,..)

class BaseClass{
    String name = "Base";
    BaseClass(String name){
        this.name = name;
    }
}
class SubClass extends BaseClass{
    SubClass(String name){
        super(name);
    }
 
}

基礎類別可以使用子類別代替

有一個基礎類別叫手機,它的類別是蘋果手機

有一位回收商人要收手機,你就可以把蘋果手機給他,因為蘋果手機是手機的一種

如果這位商人要收蘋果手機,你就不可以把全部的手機給他,因為不是全部的手機都是蘋果手機

這有相關的原則里氏替代原則

對於靜態與動態語言雖然處理上不一樣,但你要懂這原理並活用

標籤:

更新時間: