物件導向-繼承
物件導向-繼承
| TaiwanPhone |
|---|
| User |
| PhoneNumber |
| GooleMap() |
| UberEat() |
| FB() |
| Youtube() |
| Bank(string passWord) |
| ChinaPhone |
|---|
| PhoneNumber |
| BaiduMap() |
| BiliBili() |
| Bank(string passWord) |
業務增加,手機要賣向中國,設計了一個新的大陸手機的類別
然後不幸的是,我們跟中國的電話號碼格式不一樣
想要加入一個方法去處理這個問題,但是要兩邊都加嗎?有一點沒效率又難維護
讓相同的程式反覆出現在不同的類別沒效率又容易出錯,這時候可以時候繼承
Phone類別使用繼承,解決重複問題
TaiwanPhone和ChinaPhone有許多相似的程式碼,因為現實世界也是這樣子,有很多相似的地方
比較一般化的類別,稱為基礎類別。較為特殊化的類別稱為子類別,可以繼承基礎類別


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

從基礎類別繼承來的方法,不代表子類別要用同樣的方法去使用它
現實的分組其實更複雜

頂層的基礎類別,下面會有一蠍子類別,這些子類別也會有一些子類別繼承他們,這不只可以 避免很多重複的程式碼,也會讓你更好維護與閱讀你的程式
子類別可以為自己擴充
子類別並不是只能繼承來自基礎類別的欄位與方法,也能增加自己的欄位與方法 如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);
}
}
基礎類別可以使用子類別代替
有一個基礎類別叫手機,它的類別是蘋果手機
有一位回收商人要收手機,你就可以把蘋果手機給他,因為蘋果手機是手機的一種
如果這位商人要收蘋果手機,你就不可以把全部的手機給他,因為不是全部的手機都是蘋果手機
這有相關的原則里氏替代原則
對於靜態與動態語言雖然處理上不一樣,但你要懂這原理並活用