iT邦幫忙

2025 iThome 鐵人賽

DAY 11
0

前言

在前一篇中,學會了如何使用屬性與封裝來保護資料,讓類別更安全也更有彈性。不過,目前我們建立物件的方式是:

Person p = new Person();
p.Name = "小明";
p.Age = 20;

這樣需要先「建立物件」,再逐一設定屬性,如果一個類別有很多屬性,這會顯得繁瑣。因此,C# 提供了建構子(Constructor) 與物件初始化器(Object Initializer),讓我們在建立物件時就能同時完成設定。


繼承 (Inheritance) — 建立更專門化的行為

概念

繼承 (Inheritance) 與封裝 (Encapsulation)、多型 (Polymorphism) 並列為物件導向程式設計三大特性。

  • 基底類別 (Base Class):被繼承的類別。
  • 衍生類別 (Derived Class):繼承基底類別成員的類別。
  • 衍生類別可以 重複使用、擴充、修改 基底類別的功能。
  • 單一繼承:在 C# 中,一個類別只能有一個直接基底類別。
  • 可傳遞性:如果 ClassC : ClassB,而 ClassB : ClassA,那麼 ClassC 會同時繼承 ClassB 與 ClassA 的成員。
    🌟概念上,衍生類別是基底類別的「更專門化 (specialization)」。

繼承特性

  • 衍生類別會 自動繼承基底類別的所有成員(除了建構函式與解構函式)。
  • 可以在衍生類別中新增自己的成員。
  • 可以覆寫 (override) 基底類別的虛擬方法,提供不同的行為。
    可以參考以下圖片來了解 Object、WorkItem、ChangeRequest之間的差異:

範例說明

以下範例展示了三個類別的繼承關係:

  • System.Object → 所有類別的基底類別
  • WorkItem → 繼承 Object,並新增一些欄位與方法
  • ChangeRequest → 繼承 WorkItem,並新增自己的屬性與建構子

類別圖:
WorkItem 繼承 Object,新增了 6 個成員 (ID, Title, Description, jobLength, Update, WorkItem constructor)。
ChangeRequest 繼承 WorkItem,新增了 originalItemID 與自己的建構子。

https://ithelp.ithome.com.tw/upload/images/20250923/20178767ueP9sGBi9w.png

// WorkItem 類別,繼承 Object
public class WorkItem
{
    private static int currentID;

    protected int ID { get; set; }
    protected string Title { get; set; }
    protected string Description { get; set; }
    protected TimeSpan jobLength { get; set; }

    // 預設建構子
    public WorkItem()
    {
        ID = 0;
        Title = "Default title";
        Description = "Default description.";
        jobLength = new TimeSpan();
    }

    // 帶參數的建構子
    public WorkItem(string title, string desc, TimeSpan joblen)
    {
        this.ID = GetNextID();
        this.Title = title;
        this.Description = desc;
        this.jobLength = joblen;
    }

    // 靜態建構子
    static WorkItem() => currentID = 0;

    protected int GetNextID() => ++currentID;

    public void Update(string title, TimeSpan joblen)
    {
        this.Title = title;
        this.jobLength = joblen;
    }

    // 覆寫 Object.ToString()
    public override string ToString() =>
        $"{this.ID} - {this.Title}";
}

// ChangeRequest 繼承 WorkItem
public class ChangeRequest : WorkItem
{
    protected int originalItemID { get; set; }

    public ChangeRequest() { }

    public ChangeRequest(string title, string desc, TimeSpan jobLen,
                         int originalID)
    {
        this.ID = GetNextID();
        this.Title = title;
        this.Description = desc;
        this.jobLength = jobLen;
        this.originalItemID = originalID;
    }
}

使用:

// 建立 WorkItem 物件
WorkItem item = new WorkItem("Fix Bugs",
                            "Fix all bugs in my code branch",
                            new TimeSpan(3, 4, 0, 0));

// 建立 ChangeRequest 物件
ChangeRequest change = new ChangeRequest("Change Base Class Design",
                                        "Add members to the class",
                                        new TimeSpan(4, 0, 0),
                                        1);

// 使用 WorkItem 的 ToString()
Console.WriteLine(item.ToString());

// 使用繼承自 WorkItem 的 Update()
change.Update("Change the Design of the Base Class",
    new TimeSpan(4, 0, 0));

// ChangeRequest 繼承了 WorkItem 的 ToString()
Console.WriteLine(change.ToString());

Output:
1 - Fix Bugs
2 - Change the Design of the Base Class


上一篇
Day10-屬性與封裝 🔒
下一篇
Day12-介面與抽象類別
系列文
30 天從 Python 轉職場 C# 新手入門12
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言