【公告】網站目前停止所有的課程訂閱服務,原有學員權益不受影響,造成不便還請見諒,我們正在打造更多課程以及圖書,包含 Python 為主的課程主題,未來將會合併且擴充目前的課程內容,提供全新課程訂閱服務,感謝學員的支持。

類別與封裝

類別封裝特定功能所需的程式碼,透過外部引用以降低應用程式開發的複雜度。

設計類別之前,首先必須釐清類別所要提供的功能,然後於類別中將其定義成一組相對應的函式實現這些功能,透過函式的引用,即可完成方法的呼叫,進行要執行的運算或是特定工作。

方法只有被呼叫時才會執行其中的程式碼,在程式執行的過程中,它就如同類別中準備好的工具,隨時可被使用。

應用程式藉由呼叫類別物件的方法,執行特定的函式運算,當一個方法被呼叫時,程式碼會跳離目前的執行位置,進入到類別中,找到對應的函式開始執行其中的程式碼,當函式執行完畢,再跳回目前呼叫方法的下一行程式碼繼續執行,直到應用程式結束。



方法 A在主程式執行的過程依序被呼叫,執行完畢之後,重新回到主程式呼叫方法之後接續執行。

假設一個名稱為 Caculator 的類別,它內部定義了一個提供加法運算的函式 add() ,以下的程式碼可以用來呼叫此函式:

Caculator cacu = new Caculator() ;
cacu.Add(a, b);

其中第一行建立 Caculator 物件,第 2 行透過點運算子連接此函式名稱對其進行呼叫,並且傳入要進行加總的兩個參數。

class Program
{
    static void Main(string[] args)
    {
        Caculator cacu = new Caculator();
        double a = 100.1;
        double b = 200.2;
        cacu.Add(a, b);
        Console.ReadKey();
    }
}
class Caculator
{
    public void Add(double a, double b)
    {
        double result = a + b;
        Console.WriteLine(result);
    }
}

以上是完整的程式碼,在 Main 當中,透過物件 cacu 呼叫 Add 方法,並且傳入 100.1 與 200.2 兩個參數,而 Caculator 類別中的 Add 函式, a 與 b 則接收傳入的兩個參數,大括裏進行加總之後作輸出。

開發應用程式的過程中,我們將特定功能的程式碼寫在建立的類別中,也就是所謂的封裝,由於每個類別都是一個獨立的功能單位,因此在功能的設計上,應該避免與外部環境或是程式功能產生聯結。

以上述的 Caculator 類別,其中的 Add 函式,調整為純粹的加總功能程式碼即可,至於輸出的部份,則依呼叫 Add 方法的應用程式作決定。

class Program
{
    static void Main(string[] args)
    {
        Caculator cacu = new Caculator();
        double a = 100.1;
        double b = 200.2;
        double result = cacu.Add(a, b);
        Console.WriteLine(result);
        Console.ReadKey();
    }
}
class Caculator
{
    public double Add(double a, double b)
    {
        double result = a + b;
        return result;
    }
}

函式 Add 函式此次直接回傳結果,並且由主程式 main 進行輸出,這樣調整的好處除了進一步簡化 Add 函式設計,可以更容易的讓不同目標介面輸出的外部程式,取得加總結果然後進行專屬的輸出工作,例如呈現於視窗介面或是網頁。

this 關鍵字

this 關鍵字用來參考物件自己,於類別內部存取本身的方法以及欄位成員,以區隔特定區塊的內部成員。

class Program
{
    static void Main(string[] args)
    {
        UnitConversion uc = new UnitConversion();
        double oz = 8;
        double ml = uc.Oztoml(oz);
        Console.WriteLine("{0} 盎司 = {1} 毫升", oz, ml);
    }
}
class UnitConversion
{
    double ml = 29.57;
    public double Oztoml(double oz)
    {
        double result = oz * ml;
        return result;
    }
}

UnitConversion是一個封裝特定單位轉換功能的類別,類別欄位 ml 表示相當於一盎司 的毫升數, Oztoml 函式參數 oz表示盎司數,其中的程式碼將 oz 乘上 ml ,轉換成對等的毫升數,取得轉換後的結果回傳。

主程式中,建立 UnitConversion 物件,引用 Oztoml 將 oz 變數值 8 傳入,輸出「8 盎司 = 236.56 毫升」的轉換結果。

以下重新調整其中的程式碼:

class UnitConversion
{
    double ml = 29.57;
    public double Oztoml(double oz)
    {
        double ml = oz*this.ml ;
        return ml ;
    }
}

為了讓程式更容易閱讀理解,這裏將原來的 result 改成 ml ,表示為盎司轉換為毫升數的結果值,但是如此會與類別的欄位 ml 衝突,為了解決這個問題,透過 this 進行引用即可。

在類別內部, this 表示類別自己,而欄位是類別成員,因此 this.ml 可以取得 UnitConversion 類跑裏面 ml 等於 29.75 這個欄位值,而函式 Oztoml 內部的 ml 則被限制於函式範圍,屬於函式成員,與 this.ml 作區隔。

重執行會得到相同的輸出結果。

方法多載

類別內部可以定義兩組以上相同名稱的函式,彼此間透過參數作區別。

class UnitConversion
{
    double a_ml = 29.57;
    double e_ml = 28.41;
    public double Oztoml(double oz)
    {
        double ml = oz * this.a_ml;
        return ml;
    }
    public double Oztoml(double oz, char ae)
    {
        double ml;
        if (ae == 'e')
            ml = oz * this.e_ml;
        else
            ml = oz * this.a_ml;

        return ml;
    }
}

進一步改寫 UnitConversion ,其中配置了兩個欄位 a_ml 是美制盎司與毫升的的換算值,而 e_ml 則是英制盎司的換算值,同時配置另外一個版本的 Oztoml 函式,其中還有第二個參數 ae ,判斷要轉換的是美制或英制盎司單位,而原來的 Oztoml 函式,則直接以美制單位進行換算,這兩組 Oztoml 函式為同名多載版本。

class Program
{
    static void Main(string[] args)
    {
        UnitConversion uc = new UnitConversion();
        double oz = 8;
        double ml = uc.Oztoml(oz);
        Console.WriteLine("{0} 美制盎司 = {1} 毫升", oz, ml);
        ml = uc.Oztoml(oz, 'e');
        Console.WriteLine("{0} 英制盎司 = {1} 毫升", oz, ml);
        Console.ReadKey();
    }
}

主程式中,現在可以根據需求,透過指定的參數來決定呼叫的方法版本,第一次僅傳入一個參數,因此呼叫的是第一個版本,接下來則另外傳入第二個參數字元「e」 ,呼叫第二個多載版本。


沒有留言: