2026-05-20 C# 學習 **接口(Interfaces)和抽象類(Abstract Classes)

2026-05-20 C# 學習 **接口(Interfaces)和抽象類(Abstract Classes)

我:
請先進入 第七階段**,學習 **接口(Interfaces)和抽象類(Abstract Classes), 這樣我才能理解妳上列的依賴注入程式

GPT:
太好了!現在讓我們進入 第七階段:學習接口(Interfaces)和抽象類(Abstract Classes)。這些概念對理解依賴注入和面向對象的靈活設計非常重要。

1. 什麼是接口(Interface)?

接口是面向對象編程中用來定義行為約定的一種工具。它是一個純抽象類型,只包含方法、屬性等的定義,而沒有任何實現。接口本身不包含任何邏輯,它就像是一些行為的藍圖或契約,任何實現這個接口的類都必須遵循這些定義。

  • 接口的關鍵特性

    • 只包含方法、屬性等的定義,沒有具體的實現。
    • 通過 interface 關鍵字來定義。
    • 一個類可以實現多個接口,這使得接口可以用來解耦提高靈活性

接口的範例

1
2
3
4
public interface IAnimal
{
void MakeSound(); // 定義一個方法,但不提供實現
}

這個接口 IAnimal 定義了一個方法 MakeSound(),但沒有提供實現,任何實現這個接口的類都需要給出這個方法的具體實現。

實現接口的類

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Dog : IAnimal
{
public void MakeSound()
{
Console.WriteLine("Bark");
}
}

public class Cat : IAnimal
{
public void MakeSound()
{
Console.WriteLine("Meow");
}
}

在這裡,DogCat 類都實現了 IAnimal 接口,因此它們必須提供 MakeSound() 方法的具體實現。這樣做的好處是,我們可以用一個接口來表示所有的動物,從而在代碼中處理不同的動物時更具有彈性。

2. 什麼是抽象類(Abstract Class)?

抽象類是一種用來描述共同特徵和行為的基類,它允許一些方法的具體實現,並且可以包含抽象方法(不具備具體實現的成員)。

  • 抽象類的特性

    • 使用 abstract 關鍵字來定義。
    • 可以包含已實現的方法(具體的邏輯)和未實現的方法(抽象的邏輯)。
    • 不能直接創建抽象類的實例,只能通過繼承它的子類來創建實例。
    • 適合用來共用多個子類的通用邏輯,同時允許子類實現自己特有的功能。

抽象類的範例

1
2
3
4
5
6
7
8
9
public abstract class Animal
{
public abstract void MakeSound(); // 抽象方法,子類必須覆寫

public void Eat()
{
Console.WriteLine("Eating...");
}
}

在這裡,Animal 類是一個抽象類,它有一個抽象方法 MakeSound(),這個方法沒有具體的實現,子類必須覆寫這個方法。此外,它還有一個具體的方法 Eat(),所有的子類都可以共用這個方法。

實現抽象類的子類

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Bark");
}
}

public class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("Meow");
}
}

在這裡,DogCat 都繼承自 Animal,它們必須覆寫 MakeSound() 方法,因為這個方法在基類中是抽象的,而 Eat() 方法則直接從 Animal 中繼承過來。

3. 接口和抽象類的區別

  • 用途

    • 接口適用於描述行為的約定,可以用來將行為抽象出來,特別適合用於需要多重行為的情境。
    • 抽象類用於表示類之間的共通特徵和邏輯,適合用於相似的類別之間共享行為和狀態。
  • 繼承

    • 接口支持多重實現,一個類可以實現多個接口,這樣可以有效地減少耦合。
    • 抽象類只能進行單一繼承,但可以實現多個接口。
  • 實現的限制

    • 接口中的所有方法都是公共的且不能有任何具體的實現。
    • 抽象類可以包含抽象和具體的方法,因此可以提供一些通用的實現以供子類使用。

4. 實戰範例

現在我們來看一個綜合的例子,利用接口和抽象類來描述不同種類的動物。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// 定義一個接口,用於描述動物的聲音
public interface IMakeSound
{
void MakeSound();
}

// 定義一個抽象類,包含通用的動物行為
public abstract class Animal
{
public abstract void Move(); // 抽象方法,必須由子類來實現

public void Eat()
{
Console.WriteLine("Eating...");
}
}

// 定義一個類 Dog,繼承自 Animal 並實現 IMakeSound 接口
public class Dog : Animal, IMakeSound
{
public override void Move()
{
Console.WriteLine("Running on four legs...");
}

public void MakeSound()
{
Console.WriteLine("Bark");
}
}

// 定義一個類 Bird,繼承自 Animal 並實現 IMakeSound 接口
public class Bird : Animal, IMakeSound
{
public override void Move()
{
Console.WriteLine("Flying in the sky...");
}

public void MakeSound()
{
Console.WriteLine("Chirp");
}
}

class Program
{
static void Main(string[] args)
{
Dog myDog = new Dog();
myDog.Move(); // 輸出: Running on four legs...
myDog.MakeSound(); // 輸出: Bark
myDog.Eat(); // 輸出: Eating...

Bird myBird = new Bird();
myBird.Move(); // 輸出: Flying in the sky...
myBird.MakeSound(); // 輸出: Chirp
myBird.Eat(); // 輸出: Eating...
}
}

在這個範例中:

  • IMakeSound 接口 用於定義所有動物應該具備的 MakeSound() 行為,不同的動物可以有不同的實現。
  • Animal 抽象類 定義了通用的 Eat() 方法和抽象的 Move() 方法,用於描述動物的移動方式。
  • DogBird 類都繼承了 Animal,並實現了 IMakeSound 接口。這樣既共用了 Animal 的通用行為,也能根據動物種類實現不同的移動和發聲方式。

5. 接口和抽象類的選擇

  • 希望強調不同類型之間的一致行為(例如動物都應該能發出聲音,但具體聲音不同)時,使用接口是最合適的。
  • 希望共用一些通用的行為或屬性(例如動物都有 Eat() 方法)時,可以使用抽象類,它可以提供部分具體的實現。
  • 在 C# 中,一個類可以實現多個接口,但只能繼承一個類,因此,如果需要支持多重行為而不增加類的繼承深度,接口會更靈活。

小結

  • 接口(Interface) 提供了一個行為的藍圖,它強制實現的類必須包含這些行為,並且可以用來解耦和靈活擴展功能。
  • 抽象類(Abstract Class) 則用來描述類之間的共性,並允許子類共享這些共性的實現。
  • 使用接口和抽象類可以使代碼模組化可重用易於擴展,在進行更複雜的設計時,它們是非常重要的工具。

現在我們已經了解了接口和抽象類的基礎,這些概念會幫助你更好地理解前面提到的依賴注入及如何減少耦合。如果有任何問題,或者想要進一步的實戰練習,隨時告訴我!

我:
妳怎樣沒有出 練習題 跟問題給我?

GPT:
抱歉,我忘記給你提供練習題和問題了!現在我來給你一些有關接口(Interfaces)和抽象類(Abstract Classes)的練習題和問題,幫助你鞏固所學知識。

實戰練習

練習 1:定義和實現接口

  1. 定義一個接口 IVehicle,包含方法 Start()Stop()
  2. 定義兩個類 CarBicycle,分別實現 IVehicle 接口。
  3. 實現 CarBicycleStart()Stop() 方法,並創建它們的實例來呼叫這些方法。

練習 2:使用抽象類

  1. 定義一個抽象類 Appliance,包含一個抽象方法 TurnOn() 和一個具體方法 TurnOff()(該方法輸出 “Turning off appliance…”)。
  2. 定義一個類 WashingMachine 繼承自 Appliance,並實現 TurnOn() 方法。
  3. 創建 WashingMachine 的實例並呼叫 TurnOn()TurnOff() 方法。

練習 3:結合接口和抽象類

  1. 定義一個接口 IPlayable,包含方法 Play().
  2. 定義一個抽象類 Instrument,包含一個抽象方法 Tune()
  3. 定義一個類 Guitar,繼承自 Instrument,並實現 IPlayable 接口。
  4. 創建 Guitar 的實例並調用 Tune()Play() 方法。

問題

  1. 問題 1:接口與抽象類的主要區別是什麼?什麼時候應該使用接口,什麼時候應該使用抽象類?

  2. 問題 2:為什麼 C# 中允許一個類實現多個接口,但只能繼承一個抽象類?

  3. 問題 3:如果一個類需要具有多種不同的行為(例如會飛和會游泳),應該如何設計類的結構以保持靈活性並降低耦合?

小練習的期望

通過這些練習,你將能夠:

  • 熟悉如何定義接口和抽象類。
  • 瞭解如何實現不同的接口以及繼承抽象類。
  • 鞏固接口和抽象類在代碼設計中的應用,並理解它們在降低耦合和提高擴展性方面的優勢。

如果你對這些練習有任何疑問,或者完成後需要我檢查你的答案,隨時告訴我。我隨時都在這裡幫助你!