C# 入門指南

單元 11 - 建構子與屬性

~~學習進度表~~

建構子 (constructor) 是建立物件 (object) 時所執行的特殊方法 (method) ,屬性 (property) 則是封裝私有欄位 (field) 後,替私有欄位設定的存取子 (accessor)

Encapsulation

「建構子」的英文原文為 constructor ,微軟官方文件提供的機器翻譯為「建構函式」,但是 C# 中只有類別,沒有函式的概念,事實上這個詞是用 C++ 的翻譯詞,因為 C++ 除了有函式的概念外,類別中與函式相仿的定義稱之為「成員函式」,實際上「成員函式」就是一般物件導向程式設計中所指的「方法」,這裡採用的是一般物件導向程式設計的翻譯詞「建構子」,由於跟微軟提供的官方文件有所不同,特此說明。

封裝 (encapsulation) 是物件導向程式設計 (object-oriented programming) 中的重要觀念之一,目的是保護欄位,不讓欄位直接被外界程式存取及修改,在 C# 中主要做法是將欄位宣告為 private ,也就是設定成私有欄位,例如

private int _seconds = 0;

_seconds 就是記錄總秒數的欄位。

以上私有欄位 _seconds 之前的底線是習慣上的寫法,目的是說這個欄位已被封裝,不加底線也是可以的。

這樣, _seconds 就只能在相同類別 (class) 中存取。

由於欄位已封裝,程式中如果要存取欄位就要定義屬性及存取子,例如

public int Minutes
{
    get {return _seconds / 60;}
    set {
        _seconds += value * 60;
    }
}

public int Seconds
{
    get {return _seconds % 60;}
    set {
        _seconds += value;
    }
}

這裡定義了兩個屬性, MinutesSecondsMinutes 中,關鍵字 get 定義的存取子是取得 Minutes 的方式,這裡是取得總秒數除以 60 的商

get {return _seconds / 60;}

關鍵字 set 定義的存取子是如果程式中設定 Minutes 之後的動作, value 是內容關鍵字,意思是指派運算子右邊的值,這裡將 value 乘以 60 ,再加入到 _second

set {
    _seconds += value * 60;
}

內容關鍵字是在特定場合才具有關鍵字的效力。

至於 Seconds 雷同,基本上就是把總秒數 _seconds 用分及秒顯示。

以下寫成完整程式,將以上的定義放入 Timer 類別中,並在 Program 類別的 Main() 方法建立 Timer 物件

using System;

namespace ClassDemo02
{
    class Timer
    {
        private int _seconds = 0;

        public Timer(int s) 
        {
            _seconds = s;
        }

        public int Minutes
        {
            get {return _seconds / 60;}
            set {
                _seconds += value * 60;
            }
        }

        public int Seconds
        {
            get {return _seconds % 60;}
            set {
                _seconds += value;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Timer t = new Timer(699);
            Console.WriteLine("{0}:{1}", t.Minutes, t.Seconds);
            t.Seconds = 10;
            Console.WriteLine("{0}:{1}", t.Minutes, t.Seconds);
            t.Minutes = 19;
            Console.WriteLine("{0}:{1}", t.Minutes, t.Seconds);
        }
    }
}

//《程式語言教學誌》的範例程式
// http://kaiching.org/
// 專案:ClassDemo02
// 檔名:Program.cs
// 功能:示範 C# 的類別
// 作者:張凱慶

Main() 中建立 Timer 型態的變數 t 之後,再將變數 tSeconds 設定 10Minutes 設定 19 ,這樣會連動替已封裝的 _seconds 增加秒數

static void Main(string[] args)
{
    Timer t = new Timer(699);
    Console.WriteLine("{0}:{1}", t.Minutes, t.Seconds);
    t.Seconds = 10;
    Console.WriteLine("{0}:{1}", t.Minutes, t.Seconds);
    t.Minutes = 19;
    Console.WriteLine("{0}:{1}", t.Minutes, t.Seconds);
}

執行結果如下

C:\ClassDemo02> dotnet run
11:39
11:49
30:49
C:\ClassDemo02>

以上介紹了與欄位相關的屬性,以及物件導向觀念中的封裝,物件導向還有其他兩個重要觀念,下一單元會繼續介紹。

相關教學影片

上一頁 單元 10 - 類別
回 C# 入門指南首頁
下一頁 單元 12 - 物件導向程式設計
回 C# 教材首頁
回程式語言教材首頁
中英文術語對照
存取子accessor
類別class
建構子constructor
封裝encapsulation
欄位field
物件object
物件導向程式設計object-oriented programming
屬性property
方法method
參考資料
1. C# 教學課程 | Microsoft Docs - 類別與物件
2. C# 程式設計手冊 | Microsoft Docs - 類別和結構
3. C# 程式設計手冊 | Microsoft Docs - 類別
4. C# 程式設計手冊 | Microsoft Docs - 物件
5. C# 程式設計手冊 | Microsoft Docs - 方法
重點整理
1. 建構子是建立物件時所執行的特殊方法。
2. 封裝是將欄位宣告為 private ,這樣欄位就只限制在類別中的程式碼可以存取。
3. 封裝後的私有欄位要另外定義屬性及存取子存取,存取子用關鍵字 getsetvalue 定義。
問題與討論
1. 什麼是建構子?為什麼要有建構子?
2. 什麼是封裝?為什麼要做封裝?
3. 什麼是存取子?為什麼要定義存取子?
練習
1. 建立一個新專案 Exercise1101 ,替 Exercise1001 專案的 IntegerDemo 類別設計建構子及屬性。
2. 建立一個新專案 Exercise1102 ,替 Exercise1006 專案的 IntegerDemo 類別設計建構子及屬性。
3. 建立一個新專案 Exercise1103 ,替 Exercise1007 專案的 IntegerDemo 類別設計建構子及屬性。