[讀書筆記 ]Stephens' C# Programming with Visual Studio 2010 24-Hour Trainer 第二十三章

  • 932
  • 0

閱讀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方法,將資料呈現出來。