第 6 課 · 約 14 分鐘 · ← 第 5 課

類與物件:帶行為的資料

類是圖紙;物件是按圖紙造出來的東西。類型別的變數持有指向那個東西的引用。三個概念:欄位裝資料,建構子完成初始化,方法做動作。

一個什麼都有類

class BankAccount
{
    public string Owner;                 // 欄位:每個物件一份

    public BankAccount(string owner)     // 建構子:在 new 時執行
    {
        Owner = owner;
    }

    public void Print()
    {
        Console.WriteLine(Owner);
    }
}

BankAccount acct = new BankAccount("Ada");   // 造它
acct.Print();

逐塊拆:public = 類外可見。建構子和類同名、沒有返回型別——它的職責是讓物件一出生就合法。new 分配記憶體並執行它。

每個物件都是自己的

class Dog
{
    public string Name;

    public Dog(string name) { Name = name; }
}

Dog a = new Dog("Ada");
Dog b = new Dog("Grace");
Console.WriteLine(a.Name);
Console.WriteLine(b.Name);        // 兩個物件,兩個 Name——不共享

static:屬於類,不屬於物件

class Counter
{
    public static int Total = 0;      // 只有一份,全員共享

    public static void Increment()
    {
        Total++;
    }
}

Counter.Increment();                 // 在類上呼叫——不需要物件
Counter.Increment();
Counter.Increment();
Console.WriteLine(Counter.Total);

你早就在用 static 成員了:Console.WriteLine、int.Parse、Math.Max——全是類上的方法,不涉及物件。經驗法則:工具方法和共享計數器用 static;"每個一份"的用例項。

屬性:長著公眾面孔的欄位

現代 C# 風格——自動屬性看起來像欄位,但它是正式成員,帶 get/set:

class Rectangle
{
    public double Width { get; set; }     // 自動屬性
    public double Height { get; set; }

    public double Area()
    {
        return Width * Height;            // 不用寫 this. —— 默默補上
    }
}

Rectangle r = new Rectangle { Width = 3, Height = 4 };   // 物件初始化器
Console.WriteLine(r.Area());

物件初始化器(new Rectangle { … })在構造後立刻設屬性——簡單的初始化不需要引數建構子。

this:名字撞車的時候

在例項程式碼裡,this 意思是"當前這個物件"。它的主業:區分引數和同名欄位:

class Dog
{
    private string name;

    public Dog(string name)
    {
        this.name = name;   // this.name = 欄位;name = 引數
    }
}

風格建議:欄位用 PascalCase(Name)或字首(_name),this. 就幾乎永遠用不上——一個程式碼庫選定一種慣例就好。

建構子出錯的樣子

只要你聲明瞭任何建構子,C# 就不再免費提供空的那個——new Person() 會報 CS1729。修法:要麼傳引數,要麼顯式補一個無參建構子。

現在就練