C#雜記 — 介面(interface)、抽象( abstract)、虛擬(virtual)之我見

莊創偉
4 min readSep 4, 2019

--

這三個東西都有點像但是又不太一樣。有點關係但又沒甚麼關係。

要理解這三者之間的差異必須從一切的源頭類別(Class)開始談起,會比較清楚。

C# 身為一個 OOP語言,自然希望程式以物件(Object)的方式進行開發,所以我們會先定義類別(Class),類別可以視為是物件的藍圖,當類別建立(New)時,就成為了一個物件

首先先簡單的定義一個簡單的車子類別。每台車子都有型號、CC數跟售價,而且都會跑。

有了藍圖後就可以依圖設計車子。我們依藍圖建立了兩台車子,一台海神、一台小50

結果兩台都跑超快,這樣好像不太對…。雖然都是車子而且都會跑,但是速度應該是有差的。而且海神跟小50之間應該有更多的差異。所以顯然這樣的設計太籠統了。

於是我們可以將這些共同項目訂為抽象(abstract)類別,由子類別繼承( extends)並將須自行定義的動作設為抽象(abstract)方法,由子類別自行覆寫(override)

抽象方法只能定義不能實作且須為公開(public)
抽象類別不能實作

跑車與機車都繼承了Car這個抽象類別並各自覆寫了run()這個方法之後,我們就可以更明確的區分跑車與機車之間的差異。

補充:
1.抽象類別不能實作。因為設計邏輯上屬於一個未完整的類別。
2.抽象類別中可以定義抽象方法但不能實作且必須為公開(public)。因為這部份是要開放給子類別複寫的。
3.抽象類別可以繼承抽象類別,但是一樣不能實作抽象方法
4.繼承抽象類別的子類必須複寫父類的的抽象方法

同時我們在跑車的類別上增加了openDoor()這個方法,並回傳為側開。但是少數車種開門方法是上掀式的,難道又要將跑車類別改成抽象類別然後再各自實作嗎?這顯然有點因噎廢食,這時候可以使用虛擬(virtual)方法

虛擬(virtual)方法可以實作並且允許繼承的子類別複寫。

補充:
1.虛擬方法必須實作
2.虛擬方法中必須為公開(public)。因為允許子類別複寫。
3.子類別可以直接引用或選擇複寫(override)虛擬方法

現在我們有了三種車款可以開始賣車了。但是有買賣就必須繳稅,所以我們新增一個計算稅率的方法。

看似這樣就完成了。但是不只有賣車要繳稅,只要是涉及買賣都須要繳稅,將繳稅這個動作放在Car這個類別顯然是不合適的。

定義這種橫跨類別的動作及屬性便是介面(Interface)

我們簡單定義一個 IProduct的介面,裡面有 model、priceTax 這兩個屬性跟方法。然後由 ShoesCar 這兩個類別去實作這個介面。

於是不論是甚麼商品只要實作了 IProduct的這個介面都會擁有繳稅這個行為真是太好了~~~~。

但是好像有哪裡怪怪的。結果都是要各自實作,繼承了這個介面除了會在編譯的時候報錯之外好像沒甚麼用啊(編譯的時候會報錯就很有用啦~~)。

介面最大的功用就是讓不同的類別之間產生關聯性。我們可以確定只要有實作了 IProduct這個介面的類別都擁有 modelTax()這兩個屬性與方法。

所以我們可以將程式改寫為

補充:
1.介面只能宣告,不能實作,且只能為公開(public)。 *預設就是公開所以不用特別加上public
2.介面可以繼承介面
3.介面不可以繼承類別
4.可以同時繼承多個介面
5.繼承介面的類別必須實作所有的屬性與方法

MSDN
介面(interface)
抽象(abstract)
虛擬(virtual)

--

--

莊創偉

學海無涯。但是為了生計還是得下海的風塵男子