多型(Polymorphism):指的是您可以有多個交替使用的類別,即使每個類別是以不同的方式來實作相同的屬性或方法。.
多型又稱同名異式,是透過動態繫結的方式讓我們在程式執行時期可以動態決定物件參考所要執行的方法,多型允許我們在程式中使用名稱相同的方法或屬性,但不須考慮當時使用的物件型別是什麼。若要設計多型,子類別就必須先覆寫父類別同名稱的方法或屬性,接著再使用父類別的物件參考來選擇所要執行子類別物件實體的方法。由於多型的使用上會在類別中建立名稱相同的成員(屬性或方法),多載(Overloading)和覆寫(Overriding)也可以建立名稱相同的成員,因此有必要釐清這兩者的概念。
本文以C#實作執行介紹。
多載(Overloading):可接受不同個數的參數或不同資料型別的參數,用來提供不同版本的屬性或方法。也就是多個方法擁有"相同名稱"但"不同參數",傳入不同參數時會執行對應的方法。
完整程式碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace C_sharp_多載
{
class cal
{
public int add(int n1, int n2)
{
return (n1 + n2);
}
public int add(int n1, int n2,int n3)
{
return (n1 + n2 + n3);
}
public int add(int n1, int n2, int n3,int n4)
{
return (n1 + n2 + n3 + n4);
}
}
class Program
{
static void Main(string[] args)
{
cal c = new cal();
Console.WriteLine("類別cal建立c...用來實現多載情況下的多型: \n");
Console.WriteLine("c.add(1,2) = "+c.add(1,2));
Console.WriteLine("c.add(1,2,3) = " + c.add(1,2,3));
Console.WriteLine("c.add(1,2,3,4) = " + c.add(1, 2,3,4));
Console.Read();
}
}
}
執行結果如下:
覆寫(overriding):子類別的成員可用來取代父類別中不適用的成員,子類別覆寫父類別的成員時,子類別與父類別的成員必須接受相同個數的參數與相同的資料型別。也就是子類別重新定義父類別的"同名同參數"方法。
如果子類別覆寫父類別的成員時,父類別成員必須宣告為Virtual。
完整程式碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Polymorphism_3
{
class Traffic
{
protected static int _miles; //miles用來記錄前進的公里數
public virtual void SpeedUp()//SpeedUp是空白,允許被子類別覆寫
{
}
}
class Car : Traffic
{
public override void SpeedUp() //覆寫覆類別的SpeedUp方法
{
_miles += 2;
Console.WriteLine("駕駛車子,加速中,前進{0}公里",_miles);
}
}
class Airplane : Traffic
{
public override void SpeedUp()
{
_miles += 15;
Console.WriteLine("駕駛飛機,加速中,前進{0}公里",_miles);
}
}
class Program
{
static void Main(string[] args)
{
Traffic r; //r是Traffic類別的物件參考
//myCar是Car類別的物件實體,同時繼承Traffic類別
Car myCar = new Car();
//myAirPlane是AirPlane類別的物件實體,同時繼承Traffic類別
Airplane myAirPlane = new Airplane();
int input;
while (true)
{
Console.Write("請問要駕駛->1.車子 2.飛機 其他.離開:");
input = int.Parse(Console.ReadLine());
if (input == 1)
{
r = myCar; //開車子,r參考指向myCar物件實體
}
else if (input == 2)
{
r = myAirPlane;//開飛機,r參考指向myAirplane物件實體
}
else
{
break;
}
r.SpeedUp();//呼叫r參考指向物件實體的SpeedUp()方法
Console.WriteLine();
}
Console.ReadKey();
}
}
}
SpeedUp方法宣告成 virtual ,因此允許被子類別覆寫藉此達到多型。
public virtual void SpeedUp()//SpeedUp是空白,允許被子類別覆寫
{
}
執行結果如下:
若使用abstract修飾詞宣告方法或屬性,即表示此方法或屬性並沒有包含實作的部分。例如:下面的Answer方法並沒有程式主體,只有方法宣告即「()」和「;」結束而已
Public abstract void Answer();
完整程式碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace c_sharp_abstract
{
public abstract class Cal
{
public abstract double Answer(int a, int b);
/*CS0500 因為 'cAL.aNSWER2()'以標記為抽象,所以他無法宣告主體。
public abstract double Answer2()
{
}*/
}
public class CalAdd:Cal
{
public override double Answer(int x, int y)
{
return x + y;
}
}
public class CalSub : Cal
{
public override double Answer(int x, int y)
{
return x - y;
}
}
public class CalMul : Cal
{
public override double Answer(int x, int y)
{
return x * y;
}
}
public class CalDiv : Cal
{
public override double Answer(int x, int y)
{
return x / y;
}
}
class Program
{
static void Main(string[] args)
{
CalAdd ca = new CalAdd();
CalSub cs = new CalSub();
CalMul cm = new CalMul();
CalDiv cd = new CalDiv();
Console.WriteLine("ca.Answer(10,20) = " + ca.Answer(10,20));
Console.WriteLine("cs.Answer(30,20) = " + cs.Answer(30,20));
Console.WriteLine("cm.Answer(2,5) = " + cm.Answer(2,5));
Console.WriteLine("cd.Answer(10,2) = " + cd.Answer(10,2));
Console.ReadKey();
}
}
}
執行結果如下:
有夢最美 築夢踏實
活在當下 認真過每一天
我是阿夢 也是Ace