C# Polymorphism - Runtime Polymorphism

Posted by Ryan Tseng on 2018-10-25

緣起

學習物件導向的時候,會常常聽到 封裝、繼承、多型 三個詞,又尤其 多型 這個詞有點難以想像,所以寫個筆記紀錄一下概念,避免忘記多型的特性。

多型的類型

之前在學多型的時候,都覺得只有一種概念,但看了官方的文件之後,多型其實有分成兩種

  • 執行時期的多型 (靜態多型)
  • 編譯時期的多型 (動態多型)

首先來看一下什麼是 Runtime 的多型

基本上函式的多載、運算子的多載都可以是一種多型

  • function overloading
    • 參數類型的不同
    • 回傳型別的不同
    • 參數順序的不同(但參數型別要不同)
    • 包含透過繼承關係來實做的多載

參數順序的不同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void Foo(int a, int b)
{
// ...
}

public void Foo(string b, string a)
{
// Valid overload
}

public void Foo(int a, int b)
{
// Invalid overload
}
  • operator overloading

我們用四邊形來描述這個情境,今天我們用一個物件 Rectangle 來定義一個四邊形,一般來說,會有長和寬兩個 Field 和取得面積的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Rectangle 
{
private int _width;

private int _height;

public Rectangle(int width, int height)
{
_width = width;
_height = height;
}

public int Area()
{
return _width * _height;
}
}

我們先建立兩個不同大小四邊形的物件

1
2
3
4
5
var r1 = new Rectangle(10, 10);
var r2 = new Rectangle(20, 20);

r1.Area().Dump();
r2.Area().Dump();

如果我們想取得 r1, r2 的總面積,這時候就需要這樣

1
2
3
4
var r1 = new Rectangle(10, 10);
var r2 = new Rectangle(20, 20);

(r1.Area() + r2.Area()).Dump();

通常就有人會想說,為什麼我不要直接加起來就好了

這真的是個好問題,因為事情總是沒有這麼簡單

1
2
3
4
var r1 = new Rectangle(10, 10);
var r2 = new Rectangle(20, 20);

(r1 + r2) // 這裡會壞掉

事情就是沒有這麼簡單,因為 C# 根本不知道兩個物件要怎麼加起來

你必須要定義出來讓 C# 知道,所以這時候就要請出 operator overloading 來幫忙

我們把多載加在 Rectangle 類別即可,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Rectangle 
{
private int _width;

private int _height;

public Rectangle(int width, int height)
{
_width = width;
_height = height;
}

public int Area()
{
return _width * _height;
}

// This is operator overloading
public static int operator+ (Rectangle a, Rectangle b)
{
return a.Area() + b.Area();
}
}

然後你就會看到很神奇的事情發生,原本上面有錯誤的 Code 現在正常了

可以直接執行了

1
2
3
4
5
6
7
void Main()
{
var r1 = new Rectangle(10, 10);
var r2 = new Rectangle(20, 20);

(r1 + r2).Dump();
}

結果會出現

1
500

結論

其實靜態的多型,算是日常生活中比較容易碰到的狀況(函式多載),運算子多載其實我也沒有很常用,大家都還是會很直覺把他呼叫 r1.Area() + r2.Area() 把它加起來。

不過我自己一開始看到官方文件說明這兩種也算是一種多型的時候,我是有點嚇到就對了,畢竟我心目中的多型一直都是大家心目中的那種多型 >///<

下一篇要講大家都覺得是那種多型的多型

參考資料