閱讀Stephens' C#教材第二十三章筆記
Chapter 23 Defining Classes.
本章將介紹如何程式中無所不在的類別(class),包含如何自建類別、如何定義一個類別、建立屬性、方法及事件讓類別真正有用。
類別是甚麼?類別可以看成一張藍圖,透過藍圖可以產生一個實例(Instance),實例的屬性、方法、事件都是遵循原類別所定義的。
類別可以看成是一個製作餅乾的模具,透過模具所生產的餅乾(實例)都有一樣的外型。
類別有些類似十七章討論過的結構(structure),也可以透過類別中的欄位,讓實例擁有計算的功能。
當然類別與結構最大的不同在於前者是參考型態(reference type),後者是實值型態(value type),當兩個都是實值型態變數,令a = b時,a會複製一份b的內容存在本身中。當兩個都是參考型態變數,令a = b時,a會複製一個指向到b所指向的記憶體空間位址,a,b兩者所指向的內容是同一個,一旦有異動,從a或b去看結果是一樣。
書中認為類別最大的好處是封裝(encapsulation),設計良好的類別可以讓使用程式時不須了解內在的運作流程。
Turtle程式示範操作者可以輸入行進的角度與距離,則程式會自動描繪出行進的軌跡,程式中宣告一個Turtle類別,該類別具有移動(move)與轉向(Direction)的方法,所以主程式可以對建立出來的Turtle實例進行角度與距離的操作,不需要撰寫Turtle如何畫線的程式。
類別的其他好處有:
將資料與程式碼集中:例如Turtle類別中集合了移動(move)、位置(position)與方向(direction)的程式,Turtle移動時不用再去確認位置與方向。
程式碼再利用:撰寫在類別中的程式可以同時給所有Turtle實例使用。
多型(Polymorphism):稍後介紹,可參考微軟網頁
設計類別的步驟:開啟專案對專案案右鍵,選擇加入-->類別,然後設定類別名稱即完成類別新增。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyProgram
{
class Employee
{
}
}
其中MyProgram式專案名稱,Employee則是專案名稱。
接下來可以在類別中加入屬性(Properties)、方法(Methoes)及事件(Events)。
屬性(Properties):與類別有關的資料,例如一個Employee有關的資料有姓名、工號等。
方法(Methoes):物件能夠執行的動作,例如一個Employee可以設計CalculateBonus方法來計算員工的年度紅利。
事件(Events):能由操作類別所觸發的狀況,例如一個Employee可能會被觸發TooManyHours的事件,當他(她)一週工作超過40小時。
在類別中還會有一個名詞叫field,它是一個資料欄位,可供類別進行資料的操作,但要小心設為public的field可能會造出沒有管制外部對它的使用,造成資料出現重大的問題,進而影響類別本身的運作。
TRY IT 23a 中示範如何設計出一個Employee類別並產生一個實例可以接收設定資料,以下是Employee的圖例與程式碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PersonClass
{
class Person
{
// Auto-implemented properties.
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
// FirstName property.
private string firstName = "";
public string FirstName
{
get
{
return firstName;
}
set
{
if (value == null)
throw new ArgumentOutOfRangeException("FirstName",
"Person.FirstName cannot be null.");
if (value.Length < 1)
throw new ArgumentOutOfRangeException("FirstName",
"Person.FirstName cannot be blank.");
// Validations passed. Save the new value.
firstName = value;
}
}
// LastName property.
private string lastName = "";
public string LastName
{
get
{
return lastName;
}
set
{
if (value == null)
throw new ArgumentOutOfRangeException("LastName",
"Person.LastName cannot be null.");
if (value.Length < 1)
throw new ArgumentOutOfRangeException("LastName",
"Person.LastName cannot be blank.");
// Validations passed. Save the new value.
lastName = value;
}
}
}
}
在類別中的方法(Methoes)其實就是一段可以執行的程式,例如Turtle類別中的move方法,可以根據使用者提供的角度與距離劃出一條線。
在類別中的事件(Methoes)是當類別出現某一種狀況時會發生的反應,例如有一個BankAccount類別,當它的餘額小於0時,會發生一件AccountOverdrawn的事件,提供系統該帳號被過度提領。
delegate(委派)在C#中指的是一種特殊的資料型態,其內所儲放的是某種事件,而非一般的資料或物件。
Delegate程式示範委派的操作,程式中有SayHi()跟SayClicked()兩個方法,委派可以將兩個方法指派給三個按鈕,程式如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Delegates
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// Define a delegate type that takes no parameters and returns nothing.
private delegate void DoSomethingMethod();
// Declare three DoSomethingMethod variables.
private DoSomethingMethod method1, method2, method3;
// Define some methods that have the delegate's type.
private void SayHi()
{
MessageBox.Show("Hi");
}
private void SayClicked()
{
MessageBox.Show("Clicked");
}
// Initialize the delegate variables.
private void Form1_Load(object sender, EventArgs e)
{
method1 = SayHi;
method2 = SayClicked;
method3 = SayHi;
}
// Invoke the method stored in the delegates.
private void method1Button_Click(object sender, EventArgs e)
{
method1();
}
private void method2Button_Click(object sender, EventArgs e)
{
method2();
}
private void method3Button_Click(object sender, EventArgs e)
{
method3();
}
}
}
同樣地,事件也可以委派,例如Turtle程式中就將OutOfBoundsEventHandler事件進行委派。
本章的練習ComplexNumbers程式示範使用自訂的ComplexNumbers類別進行複數加減乘法的操作,有關複數的介紹可參考wiki網頁
TRY IT 23b 中示範建立具有委派事件的BankAccount類別協助程式計算帳戶餘額是否不足
本章最後還有對繼承(Inheritance)與多型(Polymotphism)進行說明,詳細資料可參考微軟網頁
TRY IT 23c 中示範利用繼承新增一個Manager類別,並且利用多型的特性,將具有不同基本資料的員工都可以用ShowAddress方法,將資料呈現出來。