Home [C# 筆記][多型] 物件導向計算機 -複習
Post
Cancel

[C# 筆記][多型] 物件導向計算機 -複習

多態(多型)的語法和用法

實現多態(多型)的三個方法

  1. 虛方法virtual
  2. 抽象類abstract
  3. 接口(介面)interface

Q:什麼時候用虛方法virtual
如果這個父類有意義,能夠創建對象(物件),並且這個方法可以調用的話,可以寫成虛方法。

Q:什麼時候用抽象類abstract
如果說父類不知道如何實現,方法也不知道怎麼寫,可以用抽象類


案例:物件導向計算機

用物件導向的思想來構思

先想類,用物件導向的思想來想

  • 父類:運算符
  • 子類:+-*/

在父類、子類裡面寫什麼?
反正我們要的這幾個子類,目的就是要把把結果算出來
那是不是應該有個計算的方法呀
那麼,你父類知道子類怎麼去計算嗎?不知道
那就寫成一個抽象函數。

1
2
//運算符 父類
public abstract decimal GetResult();//計算結果

根據去算呀?得根據用戶輸入兩個數字來算啊。
而且子類都需要這兩個數字,對吧。
要傳參的話,每個子類都要傳,很麻煩呀,
乾脆寫成屬性,兩個屬性。

1
2
3
//所有運算符的父類
NumberOne, NumberTwo //兩個屬性
public abstract decimal GetResult(); //計算結果

那麼,在創建對象的時候,我是不是還需要一個構造函數,把兩個數據可以傳過去啊?對吧。

1
2
3
4
//所有運算符的父類
//3構造函數
NumberOne, NumberTwo //2兩個屬性
public abstract decimal GetResult(); //1計算結果

這個兩個屬性和構造函數,父類自己能用嗎?不能用了,純粹給子類用的

抽象類無法創建對象(物件),為什麼? 因為它沒方法,創建沒有意義

子類就好辦了,重寫父類的抽象方法

父類&子類

1
2
3
4
5
6
父類:
  1. 計算結果 public abstract decimal GetResult(); 
  2. 兩個屬性 NumberOne, NumberTwo
  3. 構造函數
子類:
  重關父類的抽象方法

模擬用戶輸入

1
2
3
4
5
6
請輸入第一個數字
numberOne
請輸入第二個數字
numberTwo
請輸入運算符
string operate

簡單工廠

現在拿到了一個運算符,要開始計算了,但有一個問題,你知道人家要的是哪個運算符嗎?不知道咩。
這時候又需要我們用什麼呀?
簡單工廠來返回一個什麼樣的計算對象出來? 由於咱們不知道你要的是哪個運算符, 所以說,我們返回一個父類對象回去

1
2
//簡單工廠:返回一個父類對象
return Father(); //裡面裝的一定是某一個子類
Q:什麼要用簡單工廠呀?

用戶在控制台輸入了一個運算符,我們應該要根據運算符,創建一個對應的計算對象,你是加的,我是創建加的,你是減的,我創建減的,對吧!但是你知道人家的是什麼嗎?不知道咩,這個時候我們就通過簡單工廠,返回一個父類,我返回一個父類,是不是屏蔽了所有子類的一個差異,對吧!因為我們己經用抽象類來實現多態了,最終我調父類的函數,這個抽象函數其實最終調的是什麼?是被子類重寫的這個函數。

處理返回的父類對象Father()

return Father(); 這樣一個父類對象回去,但這個裡面裝的一定是其中的某一個子類對象

我們拿到這個返回的Father(),我們去調用他的計算方法

1
father.計算; //計算=>抽象類裡的抽象方法

表面上雖然我調的是我自己父類裡面的抽象函數,但是,都被我每一個子類重寫了。

具體我會調哪一個類的函數,取決於你裡面裝的是誰的對象(物件)

實現計算機-多型

父類(抽象class)

寫一個父類的抽象class,這裡面提供兩個屬性,用來儲存用戶輸入的兩個數字,再提供一個抽象的計算方法,再提供一個構造函數。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//父類:所有運算符的父類
public abstract class CalcFather
{
    //提供兩個屬性,用來儲存用戶輸入的兩個數字(純粹提供給子類用)
    public decimal NumberOne { get; set; }
    public decimal NumberTwo { get; set; }

    //構造函數(純粹提供給子類用)
    public CalcFather(decimal n1, decimal n2)
    {
        this.NumberOne = n1;
        this.NumberTwo = n2;
    }

    //抽象的計算方法
    public abstract decimal GetResult();
}

子類 加法 +

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Add : CalcFather //繼承父類抽象類
{
    //構造函數
    public Add(decimal n1, decimal n2) 
        : base(n1, n2) //繼承父類的構造函數
    {
    }

    //重寫父類抽象方法
    public override decimal GetResult()
    {
        return this.NumberOne + this.NumberTwo;
    }
}

子類 減法 -

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Sub : CalcFather //繼承父類抽象類
{
    //構造函數
    public Sub(decimal n1, decimal n2)
        : base(n1, n2) //繼承父類的構造函數
    {
    }

    //重寫父類抽象方法
    public override decimal GetResult()
    {
        return this.NumberOne - this.NumberTwo;
    }
}

子類 乘法 *

1

子類 除法 /

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Div : CalcFather //繼承父類抽象類
{
    //構造函數
    public Div(decimal n1, decimal n2)
        : base(n1, n2) //繼承父類的構造函數
    {
    }

    //重寫父類抽象方法
    public override decimal GetResult()
    {
        return this.NumberOne / this.NumberTwo;
    }
}

內函式實現案例

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
static void Main(string[] args)
{
    //虛方法、抽象類、介面
    //物件導向計算機 案例
    while (true)
    {
        Console.WriteLine("請輸入第一個數字");
        decimal n1 = Convert.ToDecimal(Console.ReadLine());
        Console.WriteLine("請輸入第二個數字");
        decimal n2 = Convert.ToDecimal(Console.ReadLine());
        Console.WriteLine("請輸入要運算符");
        string operate = Console.ReadLine();

        CalcFather calc = GetCal(operate, n1, n2);
        decimal res = calc.GetResult();
        Console.WriteLine(res);
        Console.ReadKey();
    }
}
//簡單工廠
public static CalcFather GetCal(string operate, decimal n1, decimal n2)
{
    CalcFather cal = null;

    switch (operate)
    {
        case "+":
            cal = new Add(n1, n2);
            break;
        case "-":
            cal = new Sub(n1, n2);
            break;
        case "*":
            cal = new Mul(n1, n2);
            break;
        case "/":
            cal = new Div(n1, n2);
            break;
    }
    return cal;
}

完整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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
namespace 多態複習
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //虛方法、抽象類、介面
            //物件導向計算機 案例
            while (true)
            {
                Console.WriteLine("請輸入第一個數字");
                decimal n1 = Convert.ToDecimal(Console.ReadLine());
                Console.WriteLine("請輸入第二個數字");
                decimal n2 = Convert.ToDecimal(Console.ReadLine());
                Console.WriteLine("請輸入要運算符");
                string operate = Console.ReadLine();

                CalcFather calc = GetCal(operate, n1, n2);
                decimal res = calc.GetResult();
                Console.WriteLine(res);
                Console.ReadKey();
            }
        }
        //簡單工廠
        public static CalcFather GetCal(string operate, decimal n1, decimal n2)
        {
            CalcFather cal = null;

            switch (operate)
            {
                case "+":
                    cal = new Add(n1, n2);
                    break;
                case "-":
                    cal = new Sub(n1, n2);
                    break;
                case "*":
                    cal = new Mul(n1, n2);
                    break;
                case "/":
                    cal = new Div(n1, n2);
                    break;
            }
            return cal;
        }
    }
    //父類
    public abstract class CalcFather
    {
        //提供兩個屬性,用來儲存用戶輸入的兩個數字(純粹提供給子類用)
        public decimal NumberOne { get; set; }
        public decimal NumberTwo { get; set; }

        //構造函數(純粹提供給子類用)
        public CalcFather(decimal n1, decimal n2)
        {
            this.NumberOne = n1;
            this.NumberTwo = n2;
        }

        //抽象的計算方法
        public abstract decimal GetResult();
    }
    //子類 +-*/
    public class Add : CalcFather //繼承父類抽象類
    {
        //構造函數
        public Add(decimal n1, decimal n2)
            : base(n1, n2) //繼承父類的構造函數
        {
        }

        //重寫父類抽象方法
        public override decimal GetResult()
        {
            return this.NumberOne + this.NumberTwo;
        }
    }
    public class Sub : CalcFather //繼承父類抽象類
    {
        //構造函數
        public Sub(decimal n1, decimal n2)
            : base(n1, n2) //繼承父類的構造函數
        {
        }

        //重寫父類抽象方法
        public override decimal GetResult()
        {
            return this.NumberOne - this.NumberTwo;
        }
    }
    public class Mul : CalcFather //繼承父類抽象類
    {
        //構造函數
        public Mul(decimal n1, decimal n2)
            : base(n1, n2) //繼承父類的構造函數
        {
        }

        //重寫父類抽象方法
        public override decimal GetResult()
        {
            return this.NumberOne * this.NumberTwo;
        }
    }
    public class Div : CalcFather //繼承父類抽象類
    {
        //構造函數
        public Div(decimal n1, decimal n2)
            : base(n1, n2) //繼承父類的構造函數
        {
        }

        //重寫父類抽象方法
        public override decimal GetResult()
        {
            return this.NumberOne / this.NumberTwo;
        }
    }
}
This post is licensed under CC BY 4.0 by the author.

[C# 筆記] 里氏轉換(LSP)-複習

[C# 筆記][File] 工資翻倍-練習