很多講解編程的書籍在介紹類的時候就直接介紹屬性,字段,方法,事件等等,然后說下多態性,繼承性,等等,所有的這些東西對於初學者來說實在是虛無縹緲,對於什么地方該用類,該怎么設計類仍然是很模糊的,需要經驗大量的編程實踐才能摸索到里面的經驗,所以本節在講解的時候,會側重於舉例子來說明,為什么需要使用類,怎么使用類,至於類的繼承也會針對特定的情況來說明,讓大家對於類有個清晰的概念。
為什么需要使用類
理解這個問題對於學習編程的人非常的關鍵,對於有經驗的人來說,可能會回答,類可以分離功能,形成功能模塊,進而實現模塊開發,易於調試和代碼維護。對於初學者來說,鬼知道你在說什么啊!根本理解不了,需要多寫幾次類以后才能深刻的理解這些思想,所以此處會從更基礎的情況進行說明,假設我們有一台設備,上面有5個參數需要實時在軟件上顯示,作為初學者,我們會這么寫:(1s定時器模擬了讀取設備的場景)
代碼如下所示:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace WindowsFormsApp1 12 { 13 public partial class Form1 : Form 14 { 15 public Form1() 16 { 17 InitializeComponent(); 18 } 19 20 private Timer TimerReadMachine = null; 21 22 private void Form1_Load(object sender, EventArgs e) 23 { 24 //初始化時鍾 25 TimerReadMachine = new Timer(); 26 TimerReadMachine.Interval = 1000; 27 TimerReadMachine.Tick += TimerReadMachine_Tick; 28 } 29 30 private void TimerReadMachine_Tick(object sender, EventArgs e) 31 { 32 Random r = new Random(); 33 label1.Text = "溫度1:" + r.Next(100, 300) + " ℃"; 34 label2.Text = "溫度2:" + r.Next(100, 300) + " ℃"; 35 label3.Text = "溫度3:" + r.Next(100, 300) + " ℃"; 36 label4.Text = "溫度4:" + r.Next(100, 300) + " ℃"; 37 label5.Text = "溫度5:" + r.Next(100, 300) + " ℃"; 38 } 39 40 private void Form1_Shown(object sender, EventArgs e) 41 { 42 //啟動定時器 43 TimerReadMachine.Start(); 44 } 45 46 private void Form1_FormClosing(object sender, FormClosingEventArgs e) 47 { 48 if (MessageBox.Show("是否真的退出窗口?", "退出確認", MessageBoxButtons.YesNo) == DialogResult.No) 49 { 50 e.Cancel = true; 51 } 52 } 53 54 private void Form1_FormClosed(object sender, FormClosedEventArgs e) 55 { 56 } 57 58 59 private void button1_Click(object sender, EventArgs e) 60 { 61 Button button = new Button(); 62 button.Location = new System.Drawing.Point(328, 42); 63 button.Name = "button2"; 64 button.Size = new System.Drawing.Size(75, 23); 65 button.TabIndex = 0; 66 button.Text = "button2"; 67 button.UseVisualStyleBackColor = true; 68 button.Click += Button_Click; 69 70 this.Controls.Add(button); 71 } 72 73 private void Button_Click(object sender, EventArgs e) 74 { 75 MessageBox.Show("你點擊了button2"); 76 } 77 78 79 80 } 81 }
上述的代碼有部分是上一章節的代碼,所以自行忽略,如果碰到上述的情況,只是將數據顯示一下就完事了還算簡單了,但實際情況更加復雜,通常需要緩存這五個溫度的數據,一遍根據需要進行獲取計算其他的需求,比如說,溫度的幅度區間,最大值最小值,溫度的平均值,溫度變大了還是變小了判定,等等情況,所以我們會將代碼改成下面這樣的:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace WindowsFormsApp1 12 { 13 public partial class Form1 : Form 14 { 15 public Form1() 16 { 17 InitializeComponent(); 18 } 19 20 private Timer TimerReadMachine = null; 21 22 private void Form1_Load(object sender, EventArgs e) 23 { 24 //初始化時鍾 25 TimerReadMachine = new Timer(); 26 TimerReadMachine.Interval = 1000; 27 TimerReadMachine.Tick += TimerReadMachine_Tick; 28 } 29 30 int Temperature1 = 0; 31 int Temperature2 = 0; 32 int Temperature3 = 0; 33 int Temperature4 = 0; 34 int Temperature5 = 0; 35 36 private void TimerReadMachine_Tick(object sender, EventArgs e) 37 { 38 Random r = new Random(); 39 int temp1 = r.Next(100, 300); 40 int temp2 = r.Next(100, 300); 41 int temp3 = r.Next(100, 300); 42 int temp4 = r.Next(100, 300); 43 int temp5 = r.Next(100, 300); 44 label1.Text = "溫度1:" + temp1 + " ℃ " + (temp1 > Temperature1 ? "變大了" : "變小了"); 45 label2.Text = "溫度2:" + temp2 + " ℃ " + (temp2 > Temperature2 ? "變大了" : "變小了"); 46 label3.Text = "溫度3:" + temp3 + " ℃ " + (temp3 > Temperature3 ? "變大了" : "變小了"); 47 label4.Text = "溫度4:" + temp4 + " ℃ " + (temp4 > Temperature4 ? "變大了" : "變小了"); 48 label5.Text = "溫度5:" + temp5 + " ℃ " + (temp5 > Temperature5 ? "變大了" : "變小了"); 49 50 Temperature1 = temp1; 51 Temperature2 = temp2; 52 Temperature3 = temp3; 53 Temperature4 = temp4; 54 Temperature5 = temp5; 55 } 56 57 private void Form1_Shown(object sender, EventArgs e) 58 { 59 //啟動定時器 60 TimerReadMachine.Start(); 61 } 62 63 private void Form1_FormClosing(object sender, FormClosingEventArgs e) 64 { 65 if (MessageBox.Show("是否真的退出窗口?", "退出確認", MessageBoxButtons.YesNo) == DialogResult.No) 66 { 67 e.Cancel = true; 68 } 69 } 70 71 private void Form1_FormClosed(object sender, FormClosedEventArgs e) 72 { 73 } 74 75 76 private void button1_Click(object sender, EventArgs e) 77 { 78 Button button = new Button(); 79 button.Location = new System.Drawing.Point(328, 42); 80 button.Name = "button2"; 81 button.Size = new System.Drawing.Size(75, 23); 82 button.TabIndex = 0; 83 button.Text = "button2"; 84 button.UseVisualStyleBackColor = true; 85 button.Click += Button_Click; 86 87 this.Controls.Add(button); 88 } 89 90 private void Button_Click(object sender, EventArgs e) 91 { 92 MessageBox.Show("你點擊了button2"); 93 } 94 95 96 97 } 98 }
效果如下:
在實際的開發中,一台設備的參數通常是幾十個或是上百個的數量級,或許你會說,我可以定義100個label啊,假設要監視100台設備呢,還要定義10000個label嗎,顯示是不可能的,再想想如果以后碰到需要追加一個參數的時候怎么辦(或許你會說,我會和工藝部門再三確認這些參數是不是足夠了,別人也保證了以后不再添加參數,事實上這根本沒什么卵用),再添加一台設備呢,你還要再定義那么多數據嗎?
為了解決上述留下來的編程困難,我們需要用到類的知識來解決,我們想要一種什么樣子的解決方案呢,首先肯定不希望重復定義那么多的參數吧,定義一台設備也就算了,2台的話,勉強復制下算了,超過10台,即時是復制粘貼也會受不了,其次希望多一台設備的情況下,稍微修改下代碼就可以實現。
我們把一台設備定義一個類,那么屬性就很多解決了,無非就是5個參數點,那么這個類就設計完成了:
1 public class HslMachine 2 { 3 public int Temperature1 { get; set; } 4 public int Temperature2 { get; set; } 5 public int Temperature3 { get; set; } 6 public int Temperature4 { get; set; } 7 public int Temperature5 { get; set; } 8 }
設計好類后,接着開始改造代碼,把原先的代碼改造成使用類完成的:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace WindowsFormsApp1 12 { 13 public partial class Form1 : Form 14 { 15 public Form1() 16 { 17 InitializeComponent(); 18 } 19 20 private Timer TimerReadMachine = null; 21 22 private void Form1_Load(object sender, EventArgs e) 23 { 24 //初始化時鍾 25 TimerReadMachine = new Timer(); 26 TimerReadMachine.Interval = 1000; 27 TimerReadMachine.Tick += TimerReadMachine_Tick; 28 } 29 30 HslMachine machine1 = new HslMachine(); 31 32 private void TimerReadMachine_Tick(object sender, EventArgs e) 33 { 34 Random r = new Random(); 35 int temp1 = r.Next(100, 300); 36 int temp2 = r.Next(100, 300); 37 int temp3 = r.Next(100, 300); 38 int temp4 = r.Next(100, 300); 39 int temp5 = r.Next(100, 300); 40 label1.Text = "溫度1:" + temp1 + " ℃ " + (temp1 > machine1.Temperature1 ? "變大了" : "變小了"); 41 label2.Text = "溫度2:" + temp2 + " ℃ " + (temp2 > machine1.Temperature2 ? "變大了" : "變小了"); 42 label3.Text = "溫度3:" + temp3 + " ℃ " + (temp3 > machine1.Temperature3 ? "變大了" : "變小了"); 43 label4.Text = "溫度4:" + temp4 + " ℃ " + (temp4 > machine1.Temperature4 ? "變大了" : "變小了"); 44 label5.Text = "溫度5:" + temp5 + " ℃ " + (temp5 > machine1.Temperature5 ? "變大了" : "變小了"); 45 46 machine1.Temperature1 = temp1; 47 machine1.Temperature2 = temp2; 48 machine1.Temperature3 = temp3; 49 machine1.Temperature4 = temp4; 50 machine1.Temperature5 = temp5; 51 } 52 53 private void Form1_Shown(object sender, EventArgs e) 54 { 55 //啟動定時器 56 TimerReadMachine.Start(); 57 } 58 59 private void Form1_FormClosing(object sender, FormClosingEventArgs e) 60 { 61 if (MessageBox.Show("是否真的退出窗口?", "退出確認", MessageBoxButtons.YesNo) == DialogResult.No) 62 { 63 e.Cancel = true; 64 } 65 } 66 67 private void Form1_FormClosed(object sender, FormClosedEventArgs e) 68 { 69 } 70 71 72 private void button1_Click(object sender, EventArgs e) 73 { 74 Button button = new Button(); 75 button.Location = new System.Drawing.Point(328, 42); 76 button.Name = "button2"; 77 button.Size = new System.Drawing.Size(75, 23); 78 button.TabIndex = 0; 79 button.Text = "button2"; 80 button.UseVisualStyleBackColor = true; 81 button.Click += Button_Click; 82 83 this.Controls.Add(button); 84 } 85 86 private void Button_Click(object sender, EventArgs e) 87 { 88 MessageBox.Show("你點擊了button2"); 89 } 90 91 92 93 } 94 95 96 public class HslMachine 97 { 98 public int Temperature1 { get; set; } 99 public int Temperature2 { get; set; } 100 public int Temperature3 { get; set; } 101 public int Temperature4 { get; set; } 102 public int Temperature5 { get; set; } 103 } 104 }
或許你會說,你看嘛,根本沒有方便多少,而且寫的代碼還更多了,在只有一台設備的情況下,確實如你所說,代碼更難了,卻沒有實現更多的功能。但是,,,,,但是,,,,,你想想,如果你再增加一台設備呢???
1 HslMachine machine1 = new HslMachine(); 2 HslMachine machine2 = new HslMachine();
這樣就解決拉!!!!!再增加一台的話,那就再實例化一個對象,可能你又會說,我要是有100台設備,還要實例化100個對象嗎,要是如果10000台設備呢?接下來激動人心的時刻到了,假設我們有10000台設備,應該怎么做呢?
1 private HslMachine[] hslMachines = new HslMachine[10000];//聲明10000台設備的對象
這樣一來,就算你有1億台設備我也能實例化完成(假設一台設備1萬元,總值1萬億,所以幾乎不可能),需要注意的是,這個數組對象雖然實例化完成了,1萬台設備還需要自己實例化,不然就是空引用。當設備比較多的時候,再初始化數據的地方我們也要修改,不然每台設備都這么寫就要復制很多次了,這里精簡的過程就是方法的提煉,我們讓設備類支持自我初始化,所以新增一個方法:
1 public class HslMachine 2 { 3 public int Temperature1 { get; set; } 4 public int Temperature2 { get; set; } 5 public int Temperature3 { get; set; } 6 public int Temperature4 { get; set; } 7 public int Temperature5 { get; set; } 8
9 /// <summary>
10 /// 初始化數據 11 /// </summary>
12 /// <param name="r">假想r是傳進來的設備底層數據</param>
13 public void Initialization(Random r) 14 { 15 int temp1 = r.Next(100, 300); 16 int temp2 = r.Next(100, 300); 17 int temp3 = r.Next(100, 300); 18 int temp4 = r.Next(100, 300); 19 int temp5 = r.Next(100, 300); 20
21 Temperature1 = temp1; 22 Temperature2 = temp2; 23 Temperature3 = temp3; 24 Temperature4 = temp4; 25 Temperature5 = temp5; 26 } 27 }
但是這樣做了又發生一個問題,我們在窗體程序中就不知道一個數據的狀態是變大變小還是不變了,所以我們需要改造溫度的數據。使得溫度的數據也是一個類,這樣可以使得溫度數據包含更多的特性,甚至是最大值,最小值,參數名稱
1 public class MachineParameter 2 { 3 public string ParameterName { get; set; } 4 public int Temperature { get; set; } 5 public int Status { get; set; } 6 7 public int TemperatureMax { get; set; } = int.MinValue; 8 9 public int TemperatureMin { get; set; } = int.MaxValue; 10 } 11 12 public class HslMachine 13 { 14 public MachineParameter Temperature1 = new MachineParameter() 15 { 16 ParameterName = "溫度1" 17 }; 18 public MachineParameter Temperature2 = new MachineParameter() 19 { 20 ParameterName = "溫度2" 21 }; 22 public MachineParameter Temperature3 = new MachineParameter() 23 { 24 ParameterName = "溫度3" 25 }; 26 public MachineParameter Temperature4 = new MachineParameter() 27 { 28 ParameterName = "溫度4" 29 }; 30 public MachineParameter Temperature5 = new MachineParameter() 31 { 32 ParameterName = "溫度5" 33 }; 34 35 /// <summary> 36 /// 初始化數據 37 /// </summary> 38 /// <param name="r">假想r是傳進來的設備底層數據</param> 39 public void Initialization(Random r) 40 { 41 int temp1 = r.Next(100, 300); 42 int temp2 = r.Next(100, 300); 43 int temp3 = r.Next(100, 300); 44 int temp4 = r.Next(100, 300); 45 int temp5 = r.Next(100, 300); 46 47 SetValue(Temperature1, temp1); 48 SetValue(Temperature2, temp2); 49 SetValue(Temperature3, temp3); 50 SetValue(Temperature4, temp4); 51 SetValue(Temperature5, temp5); 52 } 53 54 private void SetValue(MachineParameter para,int value) 55 { 56 if(para.Temperature>value) 57 { 58 para.Status = 1; 59 } 60 else if(para.Temperature == value) 61 { 62 para.Status = 0; 63 } 64 else 65 { 66 para.Status = -1; 67 } 68 69 70 if (para.TemperatureMax < value) para.TemperatureMax = value; 71 if (para.TemperatureMin > value) para.TemperatureMin = value; 72 73 para.Temperature = value; 74 } 75 }
到此為止,設備的類已經初具成形了,如果參數想要支持更多的特性,也方便進行擴充,如果再添加一些其他的參數信息,這個類編寫的就相當棒了。接下來就是顯示了,這次假設有50台設備,只顯示一台設備,不同的設備進行手動切換顯示,並顯示參數變大變小區別。界面重新調整:
然后界面的代碼重新設計:
1 namespace WindowsFormsApp1 2 { 3 public partial class Form1 : Form 4 { 5 public Form1() 6 { 7 InitializeComponent(); 8 } 9 10 private Timer TimerReadMachine = null; 11 12 private void Form1_Load(object sender, EventArgs e) 13 { 14 //初始化時鍾 15 TimerReadMachine = new Timer(); 16 TimerReadMachine.Interval = 1000; 17 TimerReadMachine.Tick += TimerReadMachine_Tick; 18 19 int[] datas = new int[hslMachines.Length]; 20 //設備實例化 21 for (int i = 0; i < hslMachines.Length; i++) 22 { 23 hslMachines[i] = new HslMachine(); 24 datas[i] = i + 1; 25 } 26 //初始化組合框 27 comboBox1.SelectedIndexChanged += ComboBox1_SelectedIndexChanged; 28 comboBox1.DataSource = datas; 29 } 30 31 private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e) 32 { 33 //選擇發生了變化 34 ShowSpecifiedMachine(); 35 } 36 37 private HslMachine[] hslMachines = new HslMachine[50];//聲明10000台設備的對象 38 39 private void TimerReadMachine_Tick(object sender, EventArgs e) 40 { 41 Random r = new Random(); 42 43 for (int i = 0; i < hslMachines.Length; i++) 44 { 45 hslMachines[i].Initialization(r); 46 } 47 48 ShowSpecifiedMachine(); 49 } 50 51 private void ShowSpecifiedMachine() 52 { 53 int i = comboBox1.SelectedIndex; 54 HslMachine machine = hslMachines[i]; 55 ShowTemperatureChange(label1, label10, machine.Temperature1); 56 ShowTemperatureChange(label2, label9, machine.Temperature2); 57 ShowTemperatureChange(label3, label8, machine.Temperature3); 58 ShowTemperatureChange(label4, label7, machine.Temperature4); 59 ShowTemperatureChange(label5, label6, machine.Temperature5); 60 } 61 62 private void ShowTemperatureChange(Label label_1, Label label_2,MachineParameter para) 63 { 64 label_1.Text = para.ParameterName + ":" + para.Temperature + " ℃ "; 65 switch (para.Status) 66 { 67 case -1: label_2.BackColor = Color.LimeGreen; break; 68 case 1: label_2.BackColor = Color.Tomato; break; 69 default: label_2.BackColor = SystemColors.Control; break; 70 } 71 } 72 73 private void Form1_Shown(object sender, EventArgs e) 74 { 75 //啟動定時器 76 TimerReadMachine.Start(); 77 } 78 79 private void Form1_FormClosing(object sender, FormClosingEventArgs e) 80 { 81 if (MessageBox.Show("是否真的退出窗口?", "退出確認", MessageBoxButtons.YesNo) == DialogResult.No) 82 { 83 e.Cancel = true; 84 } 85 } 86 87 private void Form1_FormClosed(object sender, FormClosedEventArgs e) 88 { 89 } 90 91 92 private void button1_Click(object sender, EventArgs e) 93 { 94 Button button = new Button(); 95 button.Location = new System.Drawing.Point(328, 42); 96 button.Name = "button2"; 97 button.Size = new System.Drawing.Size(75, 23); 98 button.TabIndex = 0; 99 button.Text = "button2"; 100 button.UseVisualStyleBackColor = true; 101 button.Click += Button_Click; 102 103 this.Controls.Add(button); 104 } 105 106 private void Button_Click(object sender, EventArgs e) 107 { 108 MessageBox.Show("你點擊了button2"); 109 } 110 111 112 113 }
至此,已經將軟件開發思路大致講完,后面的類的多態性需要另開一片文章講解,一個好的軟件系統需要花大量的時間不停的去優化,調整,路漫漫其修遠兮。