---
# System prepended metadata

title: 類別與物件的觀念
tags: [視窗程式設計]

---

---
tags: 視窗程式設計
---

# 類別與物件的觀念

如果你開始感受到函式的好用，可以大幅度減少高度類似的程式碼，還能進一步讓程式更精簡，接下來你就可以進一步了解「類別與物件」。

首先，我們幫同學建立「類別」的概念，當你開始學習類別，你就開始入門 **物件導向程式設計（Object-Oriented Programming, OOP）** 了。

:::success
**恭喜你，開始脫離程式新手村。**
:::

第一次聽到類別這個東西，你一定覺得很難理解這是甚麼？沒關係，我們慢慢來，先從日常的範例想像一下：

## 假設你要騎一台機車

如果你要騎一台機車出門兜風，那要怎麼做呢？

:::info
交通安全宣導：請同學務必考取駕照後再上路。
:::

1. 你需要先幫機車加足夠的汽油
2. 跨上車，將鑰匙插入鑰匙孔，啟動引擎
3. 轉油門手把，機車就會加速往前跑
4. 如果速度太快，要放鬆油門手把，適度拉剎車手把

**以上應該你都可以理解吧？** 如果可以理解的話，你應該可以理解所謂類別的觀念。

:::info
「類別（Class）」是將生活中事物「抽象化」，或者我們將抽象化改稱為「簡化」也可以。
:::

現在我們將一台機車的功能與狀態「簡化」一下，請參考下圖：

![](https://i.imgur.com/81eznvM.png)

因此一個機車的「類別」，你可以看成就是機車的簡化概念，其中類別可以分成「**屬性(Property)**」與「**方法(Method)**」。

* 屬性：定義類別的特性
* 方法：定義類別可操作的工作

用比較簡單的方式來解釋屬性與方法。

:::info
1. 你需要先幫機車加足夠的汽油：**設定油箱屬性**
2. 跨上車，將鑰匙插入鑰匙孔，啟動引擎：**設定鑰匙插孔屬性**
4. 轉油門手把，機車就會加速往前跑：**執行油門方法**
5. 如果速度太快，要放鬆油門手把，適度拉剎車手把：**執行剎車方法**
:::

因此類別就是一種將日常事物「抽象化」或「簡化」的方式，你或許不太習慣，以後可以多練習，把生活中的事物也用類似的方式簡化，就會慢慢習慣類別的概念。

## 寫一個程式的類別

了解基本的類別概念之後，我們就直接實作，這樣更能加深你的印象。

我們繼續使用之前的**計算機程式**，將它原本計算機進行計算邏輯的部分獨立出來，變成類別，這樣更能將程式變得更有結構。因此請開啟上一章節完成的計算機程式專案，我們繼續用這個專案當範例。

首先我們跟同學介紹如何在 Visual Studio 新增一個類別的程式檔，通常它可以放在一般程式碼裡面或者獨立一個檔案，這邊我們介紹如何將類別寫成獨立檔案。

:::info
寫成獨立檔案的好處就是，你可以直接在把這個檔案複製到另一個專案檔裡面，很簡單的直接使用。
:::

![](https://i.imgur.com/2O6qLTj.png =600x)
看大圖：https://i.imgur.com/2O6qLTj.png

新增一個類別檔案的方式，請在方案總管中點選你的專案名稱上面按右滑鼠鍵，選擇加入 -> 新增項目。

![](https://i.imgur.com/ePvLrnE.png =600x)
看大圖：https://i.imgur.com/ePvLrnE.png

接著就會出現這個視窗，請確定有沒有選到類別的項目，然後名稱取名為「Calculate.cs」，名稱一樣不要用中文或違反命名規則，最後按新增的按鍵。

![](https://i.imgur.com/AaiN7VJ.png)

完成之後，你就會看到方案總管中有這個類別檔案了。對這個檔案點兩下開啟，再新增以下的程式碼。

```csharp=
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Calculator
{
    class Calculate
    {
        public float firstNumber { get; set; } = 0;  // 屬性：firstNumber 儲存第一個數字
        public float secondNumber { get; set; } = 0; // 屬性：secondNumber 儲存第二個數字

        // 相加方法
        public float Add()
        {
            return firstNumber + secondNumber;
        }

        // 相減方法
        public float Subtract()
        {
            return firstNumber - secondNumber;
        }

        // 相乘方法
        public float Multiply()
        {
            return firstNumber * secondNumber;
        }

        // 相除方法
        public float Divide()
        {
            if (secondNumber == 0)
            {
                throw new DivideByZeroException("Cannot divide by zero.");
            }

            return firstNumber / secondNumber;
        }

        // 重新設定方法
        public void Reset()
        {
            firstNumber = 0;
            secondNumber = 0;
        }
    }
}

```

### 說明
你可以仔細看一下以上的程式，其實很多語法你都看過了，例如屬性，其實有點像是宣告變數，方法則是一般的函式。然後你可以注意到，幾乎它們都是 Public 公開的，換句話說，因為有可能類別要被別的程式所使用，所以很多都是用 Public。

我們把以上的計算機類別程式(Calculate.cs)，以類似機車類別的方式，整理成下表的形式。

![](https://i.imgur.com/NUFzDsZ.png)

你可以不要先看程式內容，先看這張表格，就可以大致了解這個計算機類別可以做甚麼？並且如果你還記得計算機程式的執行邏輯，其實也是這個類別可以完成的。

:::info
1. 輸入第一個數字：**將數字存在屬性firstNumber**
2. 輸入第二個數字：**將數字存在屬性secondNumber**
3. 按等於按鍵：**執行特定的四則運算方法**
4. 按AC按鍵：**執行重新設定方法**
:::

### 類別其實有點像是海軍命名船舶常用的「船級」名稱

例如第二次世界大戰美國的有名戰艦艦級「**愛荷華級（Iowa-class Battleship）**」，**愛荷華級代表的是某個型號的戰艦**，因此會有數艘同型的戰艦，歷史上愛荷華級的戰艦包括：愛荷華號、紐澤西號、密蘇里號、威斯康辛號（還有兩艘沒有完成的）。

「類別」就類似某種型號的戰艦，只要是同一型號的戰艦，都會有類似的型態，這些戰艦就是根據類別製造出來的「物件」，之後我們會把這個概念繼續在「物件」中進一步說明。

![](https://i.imgur.com/rRvyOaO.jpg)

## 簡單的結論

類別的設計，你可以用一個整體的思考方式，來規劃程式的架構。

例如計算機程式，你可以將原來的程式邏輯，分別依照屬性與方法的概念做一個整理，再將這些程式整理成類別來使用。你可以更好的修改或調整程式，如果是其他的程式設計師也可以方便的用你寫好的類別。

甚至我們可以將屬性與方法的使用方式說清楚，別的程式設計師可以不需要深入了解你的程式內容，只要知道有甚麼屬性與方法？知道這些屬性與方法如何使用？他們就可以快速的將你的程式用在他們的專案。

:::info
何時需要做類別？老師多半都在整理程式的階段來做。
:::

## 類別可以用來建立物件

一開始跟同學介紹 **物件導向程式設計（Object-Oriented Programming, OOP）** ，那麼類別（Class）與物件（Object）有甚麼關係？以下用例子說明這兩者的差別：

:::success
* **類別**：是一個藍圖、範本、概念的設計，類別必須要 **實體化（Instance）** 成物件才能使用。
* **物件**：是一個看的到、摸的到的實體。
:::

如果舉蓋房子為例。

:::success
* **類別**：**建築設計藍圖**，決定房子的格局，有幾間房間？結構為何？只是規畫的設計圖，不能真的住進去。
* **物件**：**實際蓋好的建築**，照著設計藍圖所蓋出來的，並且可以住進去與使用的。
:::

如果以機車為例。

:::success
* **類別**：**機車設計圖**，決定機車的基本設計，設定引擎、輪胎、傳動等大小零件怎麼安裝，不能真的拿來騎。
* **物件**：**實體的機車**，照著設計圖製造與組裝的機車，可以真的拿來騎車。
:::

所以我們剛剛做好的**計算機類別**，不能直接使用，必須要先 **實體化（Instance）** 成**物件**才能使用。

## 類別建立物件

通常從類別建立成物件，語法可以類似以下：
 
```csharp=
// 類別名稱 物件名稱 = new 類別名稱();
// 例如：

Calculate calculate = new Calculate();
// 依據類別Calculate建立一個物件calculate(注意大小寫)
```

將類別建立成物件之後，你就可以把這個物件拿來使用。假設我們有一個機車類別：

```csharp=
// 依據機車類別建立一個物件「我的機車」，物件名稱你可以自己設定，只要符合變數命名規範即可
機車類別 我的機車 = new 機車類別();

我的機車.油箱 = 10;      // 加滿油箱
我的機車.鑰匙插孔 = true; // 插入車鑰匙
我的機車.油門();         // 機車加速
我的機車.剎車();         // 機車減速
```

從上面的範例來看，你就可以知道機車類別與物件的差別，物件要從類別產生，我們要操作機車，是操作機車物件。

因此如果是計算機類別，我們就可以這樣操作它的物件，假設我們要計算的是「10 + 20」：

```csharp=
Calculate calculate = new Calculate();
// 依據類別Calculate建立一個物件calculate(注意大小寫)

calculate.firstNumber = 10;      // 輸入第一個數字存在屬性firstNumber
calculate.secondNumber = 20;     // 輸入第二個數字存在屬性secondNumber
int results = calculate.add();   // 執行加法，然後把結果賦值在變數results
calculate.Reset();               // 執行重新設定，將所有屬性都回復到預設值
```

你可以注意到，要做計算工作，就只要將數值輸入到屬性，然後選擇要用哪一種四則運算並且執行那個方法，計算完成之後，就可以執行重新設定的方法，將所有屬性都回復到預設值。

之後，我們可以修改原來計算機程式的內容。

```csharp=
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Calculator
{
    /// <summary>
    /// MainWindow.xaml 的互動邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        Calculate calculate = new Calculate(); // 建立計算機物件
        int operators = -1; // 記錄選擇哪一種運算符號？0:加、1:減、2:乘、3:除、-1:重新設定

        public MainWindow()
        {
            InitializeComponent();
        }

        private void btnOne_Click(object sender, RoutedEventArgs e)
        {
            Add_Number("1");
        }

        private void btnTwo_Click(object sender, RoutedEventArgs e)
        {
            Add_Number("2");
        }

        private void btnThree_Click(object sender, RoutedEventArgs e)
        {
            Add_Number("3");
        }

        private void btnFour_Click(object sender, RoutedEventArgs e)
        {
            Add_Number("4");
        }

        private void btnFive_Click(object sender, RoutedEventArgs e)
        {
            Add_Number("5");
        }

        private void btnSix_Click(object sender, RoutedEventArgs e)
        {
            Add_Number("6");
        }

        private void btnSeven_Click(object sender, RoutedEventArgs e)
        {
            Add_Number("7");
        }

        private void btnEight_Click(object sender, RoutedEventArgs e)
        {
            Add_Number("8");
        }

        private void btnNine_Click(object sender, RoutedEventArgs e)
        {
            Add_Number("9");
        }

        private void btnZero_Click(object sender, RoutedEventArgs e)
        {
            Add_Number("0");
        }

        // 按下數字按鍵函式
        private void Add_Number(string _number)
        {
            if (txtNumber.Text == "0")
                txtNumber.Text = "";
            txtNumber.Text = txtNumber.Text + _number;
        }

        private void btnAdd_Click(object sender, RoutedEventArgs e)
        {
            Select_Operator(0);
        }

        private void btnMinus_Click(object sender, RoutedEventArgs e)
        {
            Select_Operator(1);
        }

        private void btnPlus_Click(object sender, RoutedEventArgs e)
        {
            Select_Operator(2);
        }

        private void btnDivide_Click(object sender, RoutedEventArgs e)
        {
            Select_Operator(3);
        }

        // 運算符號按鍵函式
        private void Select_Operator(int _operator)
        {
            calculate.firstNumber = Convert.ToSingle(txtNumber.Text); //將輸入文字框轉換成浮點數，再將數字存到計算機物件的firstNumber屬性裡面
            operators = _operator;
            txtNumber.Text = "0"; //重新將輸入文字框重新設定為0
        }

        private void btnDot_Click(object sender, RoutedEventArgs e)
        {
            // 確認輸入文字框中完全沒有小數點
            if (txtNumber.Text.IndexOf(".") == -1)               
                txtNumber.Text = txtNumber.Text + ".";
        }

        private void btnClear_Click(object sender, RoutedEventArgs e)
        {
            txtNumber.Text = "0";
            calculate.Reset();
        }

        private void btnEqual_Click(object sender, RoutedEventArgs e)
        {
            float finalResults = 0f; //宣告最後計算結果變數
            calculate.secondNumber = Convert.ToSingle(txtNumber.Text); //將輸入文字框轉換成浮點數，再將數字存到計算機物件的secondNumber屬性裡面

            //依照四則運算符號的選擇，進行加減乘除
            switch (operators)
            {
                case 0:
                    finalResults = calculate.Add(); // 執行加法
                    break;
                case 1:
                    finalResults = calculate.Subtract(); // 執行減法
                    break;
                case 2:
                    finalResults = calculate.Multiply(); // 執行乘法
                    break;
                case 3:
                    finalResults = calculate.Divide(); // 執行除法
                    break;
            }

            txtNumber.Text = string.Format("{0:0.##########}", finalResults); //在輸入文字框中，顯示最後計算結果，並且轉換成格式化的字串內容

            //重新設定計算機物件
            calculate.Reset();
        }
    }
}

```

## 結語

這裡介紹基本類別與物件的概念，其實它還有更多的細節與用途，同學日後還有很多機會學習物件導向的概念，但是最基本的就是類別與物件，先從最簡單的範例學起，以後你就可以慢慢入門。

以下也有幾篇網路上不錯的教學說明，建議你有機會可以多加練習與學習。

* [物件導向基礎：何謂類別(Class)？何謂物件(Object)？](https://blog.miniasp.com/post/2009/08/27/OOP-Basis-What-is-class-and-object)
* [C#學習筆記 — 物件與類別(2)](https://blog.build-school.com/2022/05/13/c%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98-%E7%89%A9%E4%BB%B6%E8%88%87%E9%A1%9E%E5%88%A52/)

{%youtube E8zO_Djb1-c %}