物件導向的三大概念中,多型屬於最難懂的一個觀念。以生活中的例子來解釋,假如在一個班級中,老師命令學生搬桌子。不論是命令學生甲或是學生乙,老師同樣都是說:把桌子搬走。但學生甲跟學生乙搬桌子的方法會不會都相同?學生甲也許是整張桌子抬起來,學生乙可能比較懶,桌子是拖著走的。
軟體中會不會遇到這樣的情況?在一個看圖軟體中,開啟圖檔是再平常不過的一件事。但圖檔的格式有千百種,每一種格式的開啟方式都不一樣,這個時候程式該怎麼寫呢?或許有人會用以下的方法:
if(filepath的副檔名為jpg)
使用開啟jpg的函式;
if(filepath的副檔名為png)
使用開啟png的函式;
.................
如果支援的格式愈多,條件判斷式勢必會增加,在這樣的情況下,程式會變得愈來愈難維護。比較好的方法應該是以下這種方式:
openfile(filepath);
把開啟檔案的功能獨立為一個功能,讓程式碼更為簡潔,但函式裡面的方法又該如何實作呢?這個時候就可以使用多型的方法。
以下的程式是一個簡單的程式:
class shade
{
private int x,y;
public shade(int x, int y)
{
this.x = x;
this.y = y;
}
public virtual void print()
{
Console.WriteLine("這是形狀,座標為({0},{0})",x,y);
}
}
class triangle:shade
{
private int lengthX, lengthY, lengthZ;
public triangle(int x,int y,int z):base(20,10)
{
this.lengthX = x;
this.lengthY = y;
this.lengthZ = z;
}
public override void print()
{
Console.WriteLine("這是三角形,邊長分別為:{0}、{0}、{0}"
,lengthX,lengthY,lengthZ);
}
}
class supTriangle:triangle
{
public supTriangle(int x,int y,int z):base(x,y,z)
{
}
public override void print()
{
Console.WriteLine("這是超級三角形");
}
}
在這裡先實作一個shade類別,之後再讓其它的類別繼承它。而所有的類別都會實作一個print函式。這個函式的主要用意就是顯示類別本身的資訊。接下來實作main函式,讓整個程式可以執行:
class Class1
{
/// <summary>
/// 應用程式的主進入點。
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: 在此加入啟動應用程式的程式碼
//
triangle a = new triangle(3,3,9);
supTriangle b = new supTriangle(3,3,12);
printInfo(a);
printInfo(b);
}
static void printInfo(shade printer)
{
printer.print();
}
}
雖然a跟b是不同的類別,但是同樣都可以丟進printInfo函式裡,函式所接受的參數為父類別shade。但是在執行類別裡的print方法時,會自動尋找適合的print。雖然是父類別shade,但supTriangle以及triangle的print方法實際上都還是存在著,所以並不會執行shade的print方法。
從多型的概念中,可以讓程式的寫作能以抽象的方法去思考。但多型的代價其實是很高的,所以在使用時要選對時機。
註:以上的程式碼是使用C#語言。