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

類別物件參考型別與實值型別

在「類別初探」文中初次討論類別時,建立以下的類別定義:

class ActiveMsg1
{
    private string helloMessage;
    public void PrintMessage()
    {
        string msg = HelloMessage;
        Console.WriteLine(msg);
    }
    public string HelloMessage
    {
        get { return helloMessage; }
        set { helloMessage = value; }
    }
}

當類別完成定義,此類別即成為一個新的型別,程式中必須建立其實體物件,以期透過物件引用其中定義的各種成員,執行相關功能。建立實體物件必須使用 new 關鍵字,過程將會產生一個指向類別實體物件所在位置的參考,假設有一個類別 EFbook ,考慮以下的程式碼:

EFbook mybook = new EFbook() ;

mybook為任意指定的變數名稱, new 關鍵字建立 EFbook 類別的實體物件,並回傳這個物件的參考,透過 = 運算子則將此物件參考儲存至 mybook 變數,此變數儲存的只是物件本身在記憶體位置的參考值,而非實際的物件,這與數值等實值有很大的差異。來看以下的程式碼:

int a1 = 100;
int a2 = a1;
a2 = 200;
Console.WriteLine(a2);
Console.WriteLine(a1);
Console.ReadKey();

首先宣告一個 int 變數 a1 並設定其值 100 , a1 這個變數確實儲存了 100 這個數值。
第二個變數 a2 被設為 a1 ,因此 a1 的值 100 儲存至 a2 ,此時 a1 與 a2 各自儲存了 100 的值,彼此並沒有關聯,接下來重設 a2 變數的值為 200 ,然後輸出 a2 與 a1 的值。

200
100

觀察輸出結果,可以看到第一行的 a2 是重設的 200 ,而 a1 則依然為其原來儲存的值 100 。
類別透過 new 建立的物件,儲存至變數的只是此物件儲存位置的「參考」,程式藉由這個變數的「參考」找到物件,接下來是另一段程式碼:

ActiveMsg1 am1 = new ActiveMsg1();
am1.HelloMessage = "Hello";
am1.PrintMessage();
ActiveMsg1 am2 = am1;
am2.HelloMessage = "Welcome";
am2.PrintMessage(); // am2 物件
am1.PrintMessage();  // am1 物件

第一行建立的變數 am1 ,設定了屬性 HelloMessage 為 「Hello」字串,接下來引用PrintMessage() 方法將其輸出,然後將宣告的第二個變數 am2 設定為 am1,此時 am1 的參考被設定給 am1 ,如此一來, am1 與 am2 雖然是兩個不同的變數,但且有指定同一個物件的參考。

當 am2 設定 HelloMessage 屬性時,根據參考找到的物件與 am1 相同,因此重設的 「Welcome」會取代原來 am1 設定的 HelloMessage 屬性值,來看輸出結果:

Hello
Welcome
Welcome

第一行輸出是 am1 初次建立所設定的 HelloMessage 屬性值。

第二行輸出則是 am2 初次建立所設定的 HelloMessage 屬性值。

由於 am2 在這裏修改了屬值,而 am1 與 am2 兩個變數參考的是同一個物件,因此原來 am1 的 「Hello」被覆寫為「Welcome」。

類別透過 new 產生的物件,因為上述特性被視為一種參考型別,而整數這一類的基本型別,變數本身儲存是實際的值,可以視為實值型別,避免物件本身的調整導致其它參考的錯誤,開發人員在學習物件導客的過程中,瞭解兩者的差異非常重要。

沒有留言: