什麼是多態(多型)?
Circle 繼承於 Shape,在完成circle 實體化之後,通過向上轉型,我們可以把 circle 類轉化為 shape類,其實這就是「多態(多型)」最簡單的例子。
1
2
Circle circle = new Circle();
Shape shape = circle;
- 內存一致、數據一樣,但表現型態多種多樣
不管是 circle 對象(物件),選是 shape 對象(物件),他們都是引用類型,指向同一塊內存地址,雖然他們所代表的數據是完全一樣的,但是表現形式卻是多種多樣的,這就是「多態(多型)」。
多態(多型)的應用場景
「多態(多型)」是面向對象(物件導向)編程重要的特徵之一,「多態(多型)」到底可以為我們解決什麼樣的實際問題呢?
鍵盤
- 一個按鍵在不同輸入法中具有不同的表現,這就是多態(多型)」
請看一下自己的鍵盤,我們鍵盤上有一個貨幣符號(shift+4),貨幣的輸出,是根據你目前使用的輸入法來決定的,每種輸入法都會對這個貨幣符號進行重新定義,一個按鍵在不同輸入法中具有不同的表現,這就是多態(多型)」典型的應用場景。
畫圖案
不同的圖案,繪製表現形式也各不相同,可以畫圓、畫方、畫三角形。
而這種對派生類的集中處理,也是「多態(多型)」應用的經典場景。
1
2
3
4
5
6
var shapeList = new List<Shape>(); //創建圖案列表
shapeList.Add(new Cicle()); //加入圓形
shapeList.Add(new Rectangle()); //加入方形
var canvas = new Canvas(); //創建畫布物件
canvas.DrawShape(shapeList); //調用畫圖方法
1
2
3
4
5
public void DrawShape(List<Shape> shapes) {
foreach (var shape in shapes) {
shape.Draw();
}
}
多態的好處
「多態(多型)」有哪些好處呢?
- 可替換性
- 可擴展性
- 接口(介面)性
- 靈活性
- 簡化性
首先,「多態(多型)」對於已存在的程式碼,具有非常高的可替換性,例如上面畫圖案的例子,「多態(多型)」它可以對圓 circle 這個類發揮作用,同樣的,它也可以對任何其他的圖形發揮相同的作用。
第二點,「多態(多型)」對程式碼具有可擴展性,增加新的子類不會影響已存在的類任何特性,以及它的運行操作規則,而新加的子類同樣也具有「多態(多型)」的功能。
還是上面的例子,在實現了方形和圓形的「多態(多型)」之後,再去添加三角形、橢圓形的多態,拓展是非常容易的。
第三點,接口(介面)性,通過方法簽名向子類提供一個共同的接口(介面),由子類來完善、或者覆蓋它而實現的,接口(介面)的概念示常重要。
第四點,靈活性,它在應用中體現了靈活多樣的操作,提高了程式碼的使用效率。
最後,簡化性,「多態(多型)」可以簡化程式碼的編寫和修改的過程,尤其可以集中處理大量對象(物件)的運算和操作。這個特點在多態的使用中非常重要、非常突出。
但要注意的是,「多態(多型)」並不能提高執行的速度,
練習
添加畫三角形
- 只需要給這個項目添加一個新的class
- 繼承
Shape - 重寫
Draw方法 shapeList添加第三個元素
1
2
3
4
5
public class Triangle : Shape {
public override void Draw() {
Console.WriteLine("畫三角形");
}
}
1
shapeList.Add(new Triangle()); //添加三角形
Shape 對象的變化,第一個迴圈,shape進入圓形畫圓,第二個回圈,shape進入方形畫方,第三個迴圈畫三角形,於是我們的程序在調用同一個方法的時候,就表現出了不一樣的行為。
當我們談到多態的時候,指的是一個過程,一個狀態。
因為我們在 Shape中使用了虛方法virtual,這就讓它的派生類(子類)獲得了重新定義這個方法的機會。
只有在程式跑起來、運行時,它的多態才會發揮功效。
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class Shape
{
public virtual void Draw()
{
Console.WriteLine("繪製圖案");
}
}
public class Cicle : Shape
{
public override void Draw()
{
Console.WriteLine("畫圓");
}
}
public class Rectangle : Shape
{
public override void Draw()
{
Console.WriteLine("畫方");
}
}
public class Triangle : Shape
{
public override void Draw()
{
Console.WriteLine("畫三角形");
}
}
public class Canvas
{
public void DrawShape(List<Shape> shapes)
{
foreach (var shape in shapes)
{
shape.Draw();
}
}
}
internal class Program
{
static void Main(string[] args)
{
var shapeList = new List<Shape>(); //創建圖案列表
shapeList.Add(new Cicle()); //加入圓形
shapeList.Add(new Rectangle()); //加入方形
shapeList.Add(new Triangle()); //添加三角形
var canvas = new Canvas(); //創建畫布物件
canvas.DrawShape(shapeList); //調用畫圖方法
Console.Read();
}
}