iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0

前言

在前面我們說明了資料類型,迴圈,條件判斷等等,這裡就要開始準備進階的瞜~~
Day 6 練習猜數字的時候,當時為了產生隨機數字,有使用new Random的這個類別。
甚麼是類別??
這裡就要逐漸的開始帶入一些物件相關或是類別的解釋摟~


自定義的類別(Class)就像是一份特殊的設計藍圖,它告訴程式如何建立一個具有特定特性和行為的物件。

可以將類別視為一個模型,用來創建實際的物件實例。

當我們定義一個類別時,實際上是在創建一種新的資料型別,可以使用這個型別在程式中建立多個不同的物件。這有助於更有組織和有效地管理程式中的資料和功能,使程式更容易理解和維護。

但是在宣告參考型別的變數時,如果沒有明確地使用 new 運算子來建立類別的實例,或者指派已經建立的相容型別的物件,那這個變數將包含一個特殊的值 null ,表示它不參考任何物件實例。

換個方式解釋

當我們談論類別時,你可以把它想像成一個特殊的設計圖,就像是一本遊戲中角色的設計書。這本設計書告訴電腦如何創造一個新的遊戲角色,包括這個角色的名字、技能、特點和外觀。

舉個例子,假設有一本設計書叫做「勇者」。
這本設計書告訴電腦,一個「勇者」應該有什麼樣的特點,比如力量、敏捷和智慧,還有什麼樣的技能,比如攻擊、防禦和治療。

當我們在遊戲中需要一個勇者角色時,我們可以參考這本設計書,告訴電腦要創造一個新的「勇者」,並給他一個名字、設定他的特點和技能。
這樣,我們就在遊戲中創造了一個實際的勇者角色,他擁有設計書中描述的特點和技能。
而類別就像是這本設計書,至於物件則是根據這本設計書創造的遊戲角色。
這有助於我們在程式中組織和管理不同種類的角色和功能,就像你可以用不同的設計書來創造不同種類的遊戲角色一樣。

宣告類別

宣告類別時需使用後方接著唯一識別碼的 class 關鍵字,如下列範例所示:

public class Customer
{
    // 這裡可以放置類別的成員,例如欄位、屬性、方法和事件等
}

在上面的程式碼中, public 是存取修飾詞,表示這個類別是公共可見的,任何程式碼都可以訪問它。

那 Customer 是類別的名稱,你可以選擇任何有效的C#識別碼名稱作為類別名稱。

類別的主體部分是用來定義類別的成員,例如欄位、屬性、方法和事件等。這些成員定義了類別的行為和資料結構。

那類別(Class)是面向物件程式設計(OOP)的基本結構,那上面有提到裡面可以包含各種不同類型的成員,其中四個常見的成員包括:

  1. Field(欄位):欄位通常表示為類別的成員變數,用於存儲對象的狀態或數據,並具有訪問修飾詞,例如 publicprivateprotected 等,以確定其可見性和訪問權限。

    class Person
    {
        // Field
        private string name;
    
        // Constructor
        public Person(string name)
        {
            this.name = name;
        }
    }
    

    再舉個欄位(Field)的例子:

    class Circle
    {
        public double Radius; // Field,存儲圓的半徑
    
        public double CalculateArea()
        {
            // Method,計算圓的面積,使用了 Radius 欄位的值
            return 3.14 * Radius * Radius;
        }
    }
    

    在上面的例子中,Circle 類別裡面有一個名為 Radius 的欄位,它存儲了圓的半徑。

    在類別中有一個方法(Method)叫做 CalculateArea,用於計算圓的面積。

    方法內部,我們使用了 Radius 欄位(Field)的值來執行計算。

  2. Method(方法): 方法是一段可重複執行的程式碼區塊,也是類別中的函數,定義在類別內部,也就是說定義了類別對外部世界可見的行為,用於執行特定的操作或功能,可以訪問和修改類別的欄位,並提供外部程式碼調用的接口。
    方法的定義包含以下部分:

    存取修飾詞(Access Modifier): 決定誰可以訪問該方法。常見的存取修飾詞包括:
    - public:該方法可以在整個專案中的任何地方訪問。
    - private:該方法只能在同一類別中訪問,對其他類別不可見。
    - 其他存取修飾詞,例如 protected(僅限同一類別和繼承的子類別訪問)、internal(同一組件內的類別訪問)等。
    返回類型(Return Type): 指定該方法返回的值的資料型別。如果方法不返回任何值,則使用 void
    方法名稱(Method Name): 用於識別該方法的名稱,必須是有效的 C# 識別符號。
    參數列表(Parameter List): 包含方法接受的參數的資訊,每個參數都包括資料型別和名稱。方法可以接受零個或多個參數。
    方法主體(Method Body): 包含實際的程式邏輯,這些邏輯會在調用方法時執行。
    例如,一個 Car 類別可以有一個 Start 方法,用於啟動汽車。
    (Method命名要大寫開頭,如下的例子,Calculator就是這個Method的名稱。)

    class Calculator
    {
        // Method
        public int Add(int a, int b)
        {
            return a + b;
        }
    }
    
  3. Property(屬性): 屬性是一種特殊的方法,本質上是一對 getter 和 setter 方法的組合,用於訪問和設置類別的私有欄位(field)。
    屬性提供了封裝和保護對象數據的方式,並允許外部程式碼通過屬性訪問數據,而不是直接訪問欄位。
    例如,一個 Person 類別可能有 NameAge 屬性,用於表示人的姓名和年齡。

    class Person
    {
        // Property
        public string Name { get; set; }
    
        // Constructor
        public Person(string name)
        {
            Name = name;
        }
    }
    
  4. Constructor(建構函數): 建構函數是特殊的方法,它在創建類別的新實例時自動被調用。建構函數的主要目的是初始化新物件的狀態,設定其屬性的初始值,或進行其他初始化操作。以下是有關建構函數的更多解釋:

    建構函數名稱與類別名稱相同:C#中的建構函數與類別的名稱相同,這是它們的特殊之處。當你創建一個新的類別實例時,編譯器會自動選擇相應的建構函數來初始化該實例。可以看到下面的程式碼,有一個名為**Person**的類別,裡面也有個與類別同樣是 Person 這個名稱的就是建構函數。

    class Person
    {
        // 建構函數
        public Person()
        {
            // 初始化操作
        }
    }
    

    多個建構函數(多載):多載(Overloading)是指在同一個類別中可以定義多個具有相同名稱但參數列表不同的方法或建構函數(也就是說一個類別可以有多個建構函數)。

    當你呼叫這個方法或建構函數時,編譯器會根據傳入的參數數量或類型來決定使用哪個版本。
    每個建構函數可以接受不同數量或類型的參數,這樣在創建物件時可以根據需要選擇不同的建構函數。

    class Person
    {
        public string Name { get; set; }
    
        // 建構函數1:預設建構函數,不接受參數
        public Person()
        {
            Name = "Unknown";
        }
    
        // 建構函數2:接受名稱作為參數
        public Person(string name)
        {
            Name = name;
        }
    
        // 建構函數3:接受名稱和年齡作為參數
        public Person(string name, int age)
        {
            Name = name + " (Age: " + age + ")";
        }
    }
    

    上面的程式碼裡面有三個建構函數:一個不接受參數,一個接受名稱,還有一個接受名稱和年齡。

    在下面這裡new這些來建立實例。

    Person person1 = new Person();            // 使用預設建構函數,Name將是"Unknown"
    Person person2 = new Person("John");      // 使用接受名稱的建構函數,Name將是"John"
    Person person3 = new Person("Alice", 30); // 使用接受名稱和年齡的建構函數,Name將是"Alice (Age: 30)"
    

    上面這裡就可以看到,根據需要使用不同版本的建構函數,以初始化物件的狀態。

    初始化操作:建構函數通常用於執行初始化操作,例如設定屬性的初始值。在建構函數中,你可以訪問類別的成員並對它們進行操作。這有助於確保新建立的物件處於一個已知的狀態。

     ```csharp
     class Person
     {
         private string name;
    
         // 建構函數
         public Person(string initialName)
         {
             name = initialName; // 初始化名稱
         }
     }
     ```
    

    總之,建構函數是在創建類別的新實例時執行的特殊方法,用於初始化物件的狀態。建構函數的名稱與類別名稱相同,可以有多個不同的建構函數,每個都可以接受不同的參數。建構函數通常用於執行初始化操作,確保物件處於一個合適的狀態。

這四個成員類型(欄位、方法、屬性和建構函數)是類別中常見的結構元素,它們一起定義了類別的行為和屬性。通過組合和使用這些成員,可以建立具有特定功能和數據結構的類別,以滿足程式碼設計需求。

屬性(Property)和欄位(Field)的差異:

  1. 訪問權限: 屬性(Property)通常應該具有 publicprotected 訪問修飾符,以提供外部程式碼訪問對象的屬性值的界面。欄位(Field)則通常應該具有 private 訪問修飾符,以限制直接訪問,鼓勵使用屬性。
  2. 可驗證性: 屬性(Property)在讀取和設置值時執行額外的驗證和邏輯處理。欄位通常不具備這種驗證功能。
  3. ReadOnly 和 WriteOnly 屬性: 屬性可以定義為唯讀(ReadOnly)或唯寫(WriteOnly)。
  4. 命名慣例: 屬性通常(單詞首字母大寫),而欄位通常使用 camelCase 命名慣例(第一個單詞小寫,後面的單詞首字母大寫),有助於區分它們。

下面這裡來解釋要創建一個物件實例,需要使用 new 關鍵字。

// 自定義的類別
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

// 創建並初始化一個 Person 類的實例
Person person = new Person();
person.Name = "John";
person.Age = 30;

類別定義:你首先定義一個類別,這個定義包括類別的名稱、欄位、屬性、方法等。這個定義告訴編譯器如何建立和操作這種型別的物件。例如:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

在上面的例子中,我們定義了一個名為 Person 的類別,它具有 Name 和 Age 兩個屬性。

物件實例化:要使用 Person 這個類別來創建一個實際的物件,你需要使用 new 關鍵字,這個過程稱為物件實例化。例如:

Person person = new Person(); // 使用new關鍵字創建Person類別的物件實例

當你執行上面這行程式碼時,會建立一個名為 person 的物件實例,該物件符合 Person 類別的定義,並可以向上面類別定義給的示範程式碼一樣存儲 Name 和 Age 等屬性。

物件初始化:一旦你有了物件實例,你可以初始化它的屬性。例如:

person.Name = "John";
person.Age = 30;

上面的程式碼裡面可以看到,我們為 Person 物件的 Name 和 Age 屬性賦值,Name給他”John”,Age給30的值。

當我們定義類別就只是定義了一個物件的模板,直到我們使用 new 關鍵字才能真正創建該物件的實例。
物件實例是基於類別定義的,它包含了該類別所描述的屬性和行為。
而物件實例化是在程式執行時創建物件的過程,讓我們可以在程式中操作和使用這些物件。


當設計和使用類別時,以下幾個重要原則和指南,可以幫助確保程式碼的品質和可讀性:

  1. 屬性可見性:

    • 通常,屬性應該是 public,以便其他程式碼可以訪問和設置它們的值。
    • 但如果某個屬性只需在類別內部使用,應將其設為 private
    • 如果需要在類別和其子類別之間訪問,可以使用 protected
  2. 屬性的實作:

    • 在 C# 中,可以使用自動實作屬性 (Auto-Implemented Properties)。

      自動實作屬性(Auto-Implemented Properties)是一種簡化的屬性定義方式,允許您定義一個屬性,而不必明確實作其 get 和 set 存取子方法。這種屬性會自動綁定到內部的隱藏字段,編譯器會自動處理存取屬性值的邏輯。

      在 C# 中,您可以使用以下方式定義自動實作屬性:

      public int MyProperty { get; set; }
      

      這裡的 MyProperty 是屬性的名稱,而 get;set; 是存取子的定義,但它們是空的。這表示您不需要自己撰寫 get 和 set 存取子的實作,編譯器會自動為您生成。

      當您訪問這個屬性時,編譯器將自動處理屬性值的讀取和寫入。例如,您可以這樣使用自動實作屬性:

      MyClass obj = new MyClass();
      obj.MyProperty = 42; // 寫入屬性值
      int value = obj.MyProperty; // 讀取屬性值
      

      在這個示例中,編譯器會自動創建一個內部的隱藏字段來存儲 MyProperty 的值,並生成相應的 get 和 set 存取子,使您可以像訪問字段一樣訪問屬性。

      自動實作屬性特別適用於簡單的屬性,不需要額外的邏輯處理,例如存儲和擷取值。如果需要在屬性設置或讀取值時執行複雜的邏輯,則可能需要使用常規的屬性,並自行實作其存取子。

    • 可以使用 Visual Studio 的簡化方式
      像是 prop 快捷鍵,可以打prop 按Tab ⇒
      https://ithelp.ithome.com.tw/upload/images/20230921/20151470fgJueSlmPR.png

    • 系統就會自己跳出 public int MyProperty {get ; set;} ,再按Tab

    • ⇒ 就會先跳到int,可以選擇是否更改類別成string 或bool,再按Tab

    • ⇒ 就會跳到MyPropety,然後再進行命名
      https://ithelp.ithome.com.tw/upload/images/20230921/20151470eo5BWJq2Rh.png

    還有 ctor 快捷鍵,可以打ctor(或打ct出現如下圖所示) 按Tab ⇒
    https://ithelp.ithome.com.tw/upload/images/20230921/201514702V55fBNOQ9.png
    這時候就會自動產生建構函數出來,如下圖所示。
    https://ithelp.ithome.com.tw/upload/images/20230921/20151470hMnSmjapDn.png

  3. 屬性的命名:

  • 屬性名稱應該使用 PascalCase(每一個單字的首字母都採用大寫字母)駝峰式命名慣例。
  • 命名應該具有描述性,以清楚表示屬性的用途。
  1. 欄位(Fields):
    • 欄位通常應該是 private,以限制直接訪問,並使用屬性來進行封裝。
    • 欄位命名應該使用 camelCase(首字母小寫,第一個單字後的單字首字母都採用大寫字母)駝峰式命名慣例。
  2. 建構函數:
    • 建構函數是初始化物件的好地方,並應該確保物件處於一個一致的狀態。
    • 可以有多個建構函數(多載),以便根據需要進行初始化。
    • 建構函數應該根據需求接受參數,並使用這些參數來初始化物件的屬性。
  3. 可見性和封裝:
    • 保持封裝,只暴露必要的屬性和方法。
    • 使用 privateprotectedpublic 等關鍵字來定義適當的可見性。
  4. 方法:
    • 方法名稱應該使用 PascalCase (每一個單字的首字母都採用大寫字母)駝峰式命名慣例。
    • 方法應具有描述性名稱,清楚表示其功能。
    • 適當地使用 publicprivateprotected,以確保方法的可見性。
  5. 註釋和文件:
    • 使用註解來說明類別、屬性和方法的用途。
    • 為公共類別、屬性和方法提供文件,以便其他人了解如何使用它們。

總之,良好的程式碼設計是保持程式可讀性和可維護性的關鍵。遵循這些原則有助於創建乾淨、明瞭且易於理解的程式碼。


第九天挑戰完成~很快速地來到了這裡,剛學這裡的時候大概的基礎知識跟原則知道,但如何使用其實並不是那麼清楚。
但很慶幸最初的時候在參考使用這些原則的時候有認真去理解為什麼要這樣做,才能讓自己在之後大量練習以後漸漸知道程式碼哪些地方還可以再做更好的,雖然還是有很多需要了解學習的地方呀~鼓勵自己持續加油呀~


上一篇
Day 8 數值格式化 StringBuilder 類型轉換
下一篇
Day 10 深入了解C#函數(Functions)的原理和用法
系列文
30天開啟.NET後端工程師的旅程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言