C# 入門指南 - setget

屬性 (property) 需要有效的封裝 (encapsulation) 到物件 (object) 裡頭,因此類別 (class) 定義屬性時,應該宣告 (declare) 為 private ,也就是私有的,只限所屬類別可以存取,然後另外定義宣告為 publicsetget 方法 (method) ,利用 set 設定屬性,另外用 get 取得屬性值




為什麼要這麼做呢?理由其實很簡單,為了防止物件遭不當的使用,例如
Encrypt t = new Encrypt(); 
t.cArray = "a"; // 重新將 cArray 設定為另一個字串


Encrypt 型態的變數 t 先以建構子 (constructor) 建立新物件,然後突然將 cArray 重新設定為對另一個字串的參考,這樣一來,原先的對換表格就不見了說,之後加入編碼與解碼的方法,若使用錯誤的表格,就會造成難以回復的結果。雖然這是我們刻意弄的例子,自己寫程式真實情況常常會有打錯字之類的,例如有個屬性 a 原本要設定為 1 ,結果按成 0
t.a = 0; // 把 a 設定錯誤


當然,我們自己開發程式可以自己小心點就好,但是,假如我們開發出的類別有提供給別的程式設計師或開發團隊使用的話,別人就不見得會這麼小心了。因此,物件導向程式設計 (object-oriented programming) 中提供封裝的意義即在此,類別的屬性應該宣告為 private
private string cArray;


setget 都是關鍵字 (keyword) 之一,這裡,我們依 C# 的習慣設置另一個成員 (member) Code ,利用 Code 來存取 cArray ,其中包含 setget 的設定,如下
public string Code {
    get { return cArray; }
    set { 
        if (value is string && value.Length == 26) {
            cArray = value; 
        }
        else {
            System.Console.WriteLine("something worng!!");;
        }
    }
}


get 很簡單,就只是回傳 cArray , set 比較複雜一點,我們加進型態檢查與字串長度檢查。 value 亦為關鍵字,這是表示指派時等號右邊的值
e.Code = value;


is 為判斷型態相等的關鍵字。 && 後面是字串長度檢查, Length 為字串長度,這裡會判斷 value 是否為 26 ,也就是密碼表的長度。 && 為邏輯運算子 (logical operator) ,也就是說,只有當 value 的型態為字串且字串長度為 26 之時, value 的值會被設定為 cArray 。


這樣的方式雖然還未臻完美,但已經可以有效阻止 cArray 被任意修改。


完整的 Encrypt 修改如下
class Encrypt {
    private string cArray;
    
    public string Code {
        get { return cArray; }
        set { 
            if (value is string && value.Length == 26) {
                cArray = value; 
            }
            else {
                System.Console.WriteLine("something worng!!");;
            }
        }
    } 
        
    public Encrypt() {
        System.Random r = new System.Random();
        int a = 0;
        int b = 0;
        // 限定 a 為偶數
        while (a % 2 == 0) {
            a = r.Next(1, 10);
            b = r.Next(1, 10);
        }
        System.Console.Write("a: " + a + ", b: " + b + ", "); 
            
        int x, y, m;
        char c = 'a';
        int i;
        System.Text.StringBuilder s = new System.Text.StringBuilder();
        for (i = 0; i < 26; i++) {
            x = c;
            y = x * a + b;
            m = y % 26;
            s.Append((char) (m + 97)); 
            c++; 
        }
    
        this.cArray = s.ToString();   
    }
    
    static void Main() {
        Encrypt e = new Encrypt();
        System.Console.WriteLine("e: "+ e.cArray);
        e.Code = "abcdefghijklmnopqrstuvwxyz";
        System.Console.WriteLine("e: "+ e.cArray);
        e.Code = "abcd";
        System.Console.WriteLine("e: "+ e.cArray);
        e.Code = "1234";
        System.Console.WriteLine("e: "+ e.cArray);
    }
}

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:encrypt.cs
    功能:示範 C# 程式 
    作者:張凱慶
    時間:西元 2012 年 10 月 */


同樣的, Main() 也有作些修改來測試,編譯執行結果如下




有沒有看到,不符規格的字串無法成功設定 cArray 。好了,接下來,我們替 Encrypt 加入編碼的功能吧!


中英文術語對照
屬性property
封裝encapsulation
物件object
類別class
宣告declare
方法method
建構子constructor
物件導向程式設計object-oriented programming
關鍵字keyword
成員member
邏輯運算子logical operator


您可以繼續參考
軟體開發


相關目錄
回 C# 入門指南
回 C# 教材
回首頁


參考資料
http://msdn.microsoft.com/zh-tw/library/ms228503%28v=vs.80%29.aspx
http://msdn.microsoft.com/zh-tw/library/ms228368%28v=vs.80%29.aspx
http://msdn.microsoft.com/zh-tw/library/a1khb4f8%28v=vs.80%29.aspx
http://msdn.microsoft.com/zh-tw/library/x9fsa0sw%28v=vs.80%29.aspx
http://msdn.microsoft.com/zh-tw/library/w86s7x04%28v=vs.80%29.aspx
http://msdn.microsoft.com/zh-tw/library/k69wcs43%28v=vs.80%29.aspx

1 則留言:

吳東諺 提到...

System.Console.WriteLine("e: "+ e.cArray);

是不是要改成

System.Console.WriteLine("e: "+e.Code);

cArray已目經設為private的就是要保護他

這邊直接讀取是無法的

應該透過get function,得到cArray的值,對吧?