# 第7章 繼承、多型、介面 ## :book:繼承 # 繼承 (Inheritance) 指的是一種面向對象編程技術,它允許我們從已有的類別(基類或父類)創建新的類別(派生類或子類)。繼承的主要目的是促進代碼重用和結構化,使我們可以在派生類中使用基類的屬性和方法,同時還可以添加新的屬性和方法或修改基類的行為。 ## 基本概念 ### 1.基類 (Base Class) 基類是被繼承的類。基類提供了派生類將繼承的基本屬性和方法。 ### 2.派生類 (Derived Class) 派生類是從基類繼承的類。派生類可以使用基類的屬性和方法,並可以添加自己的屬性和方法。 ## 繼承的語法 在 C# 中,繼承使用 : 符號,後面跟著基類的名稱。派生類繼承基類的語法如下: ## 範例 ```C#= class A// 定義基類 A { public void E() { Console.WriteLine("Eating..."); } public void S() { Console.WriteLine("Sleeping..."); } } class Dog : A// 定義派生類 D,繼承自 A { public void B() { Console.WriteLine("Barking..."); } } class Program// 主程序 { static void Main(string[] args) { D my D= new D(); my.DEat(); // 繼承自 A my.DSleep(); // 繼承自 A my.DBark(); // D 自己的方法 } } ``` **D** 類繼承了 **A** 類,因此 **D** 類的實例可以使用 **A** 類中的 **E** 和 **S** 方法 ## 繼承的特性 ### 1.單一繼承 (Single Inheritance) 在 C# 中,一個類只能繼承一個基類,這稱為單一繼承。 ### 2.多重層次繼承 (Multilevel Inheritance) 一個類可以作為另一個類的基類,從而形成繼承鏈。例如:A → B → C,其中 B 繼承自 A,C 繼承自 B。 ```C#= class A { public void MethodA() { Console.WriteLine("MethodA in A"); } } class B : A { public void MethodB() { Console.WriteLine("MethodB in B"); } } class C : B { public void MethodC() { Console.WriteLine("MethodC in C"); } } class Program { static void Main(string[] args) { C objC = new C(); objC.MethodA(); // 從 A 繼承 objC.MethodB(); // 從 B 繼承 objC.MethodC(); // 自己的方法 } } ``` ### 3.方法重寫 (Method Overriding) 當基類中的方法被標記為 **virtual** 並且在派生類中被重寫時,派生類可以修改該方法的實現。重寫的方法需要使用 **override** 關鍵字。 ```C#= class A { public virtual void Speak() { Console.WriteLine("A sound"); } } class D : A { public override void Speak() { Console.WriteLine("Bark"); } } class Program { static void Main(string[] args) { A myD = new D(); myD.Speak(); // 輸出 "Bark" } } ``` **Speak** 方法在 **D** 類中被重寫,因此即使 **myD** 的類型是 **A**,它仍然會調用 **D** 類中的 **Speak** 方法。 ## 使用基類構造函數 派生類可以通過 **base** 關鍵字調用基類的構造函數,以確保基類的初始化。 ```C#= class A { public A() { Console.WriteLine("A constructor"); } } class D : A { public D() : base() { Console.WriteLine("D constructor"); } } class Program { static void Main(string[] args) { D myD = new D(); // 輸出: // A constructor // D constructor } } ``` **D** 的構造函數會首先調用 **A** 的構造函數,然後再執行自己的構造函數。 ## 使用保護修飾符 (Protected Access Modifier) 基類中的保護成員(protected)可以被派生類訪問,但不能被其他類訪問。 ```C#= class A { protected void Breathe() { Console.WriteLine("Breathing..."); } } class D : A { public void UseBreathe() { Breathe(); // 可以訪問 } } class Program { static void Main(string[] args) { D myD = new D(); myD.UseBreathe(); // 輸出 "Breathing..." } } ``` **Breathe** 方法在 **D** 類中是可訪問的,但在 **Program** 類中不可訪問。 # 多型(Polymorphism) 是面向對象編程的一個核心概念,它允許對象以多種形式出現。多型性使得相同的方法可以有不同的行為,從而提高代碼的靈活性和可擴展性。C# 中的多型性主要通過**方法重載**(Overloading)和**方法覆寫**(Overriding)來實現。 ## 方法重載 (Method Overloading) 方法重載是指在同一個類中,可以有多個同名的方法,但它們的參數列表不同(參數的數量或類型不同)。方法重載是編譯時多型(Compile-time Polymorphism)。 ### 範例: ```C#= class MathOperations { public int Add(int a, int b) { return a + b; } public double Add(double a, double b) { return a + b; } public int Add(int a, int b, int c) { return a + b + c; } } class Program { static void Main(string[] args) { MathOperations math = new MathOperations(); Console.WriteLine(math.Add(1, 2)); // 輸出: 3 Console.WriteLine(math.Add(1.5, 2.5)); // 輸出: 4.0 Console.WriteLine(math.Add(1, 2, 3)); // 輸出: 6 } } ``` **Add**方法被重載了三次,每次的參數列表都不同。 ## 方法覆寫 (Method Overriding) 方法覆寫是指在基類中定義了一個方法,然後在派生類中重新定義這個方法。基類的方法必須使用 **virtual** 關鍵字聲明,派生類的方法必須使用 **override** 關鍵字聲明。方法覆寫是運行時多型(Runtime Polymorphism)。 ### 範例: ```C#= class A { public virtual void Speak() { Console.WriteLine("A sound"); } } class D : A { public override void Speak() { Console.WriteLine("Bark"); } } class C : A { public override void Speak() { Console.WriteLine("Meow"); } } class Program { static void Main(string[] args) { A myA = new A(); myA.Speak(); // 輸出: A sound myA = new D(); myA.Speak(); // 輸出: Bark myA = new C(); myA.Speak(); // 輸出: Meow } } ``` **Speak** 方法在 **D** 和 **C** 類中被重寫了。因此,當我們通過基類引用來調用這些方法時,會根據實際的對象類型來調用相應的方法。 ## 抽象類和抽象方法 抽象類是不能被實例化的類,只能作為其他類的基類。抽象類可以包含抽象方法,這些方法沒有實現,必須在派生類中實現。抽象方法自動具有 **virtual** 標識符。 ### 範例: ```C#= abstract class A { public abstract void Speak(); } class D : A { public override void Speak() { Console.WriteLine("Bark"); } } class C : A { public override void Speak() { Console.WriteLine("Meow"); } } class Program { static void Main(string[] args) { A myD = new D(); myDog.Speak(); // 輸出: Bark A myC = new C(); myC.Speak(); // 輸出: Meow } } ``` **Al** 是一個抽象類,並且包含一個抽象方法 **Speak**,這個方法在 **D** 和 **C** 類中被實現。 # 介面(Interfaces) 是定義方法、屬性、事件和索引子(Indexers)的一種契約,它只描述這些成員的簽名,並不提供具體的實現。任何類別或結構實現介面時,都必須實現介面中的所有成員。介面允許多重繼承,這在 C# 中的類別繼承中是不允許的。介面是實現多型性的重要工具之一。 ## 介面的特性 ### 成員簽名 介面中只包含成員的簽名(方法、屬性、事件和索引子),不包含任何實現。 ### 多重繼承 一個類別或結構可以實現多個介面。 ### 隱式和顯式實現 類別或結構可以通過隱式或顯式方式來實現介面中的成員。 ## 定義介面 介面的定義使用 **interface** 關鍵字,語法如下: ```C#= interface IExample { // 方法簽名 void Method1(); void Method2(int param); // 屬性簽名 int Property1 { get; set; } // 事件簽名 event EventHandler Event1; // 索引子簽名 int this[int index] { get; set; } } ``` ## 實現介面 一個類別實現介面時,必須實現介面中的所有成員。語法如下: ```C#= class ExampleClass : IExample { // 實現方法 public void Method1() { // 方法實現 } public void Method2(int param) { // 方法實現 } // 實現屬性 public int Property1 { get; set; } // 實現事件 public event EventHandler Event1; // 實現索引子 public int this[int index] { get { return index; } set { /* set implementation */ } } } ``` ## 範例 ```C#= // 定義介面 interface I { void S(); void E(); } // 實現介面 class D : I { public void S() { Console.WriteLine("Bark"); } public void E() { Console.WriteLine("Dog is eating"); } } class C : I { public void S() { Console.WriteLine("Meow"); } public void E() { Console.WriteLine("Cat is eating"); } } class Program { static void Main(string[] args) { I myD = new D(); myD.S(); // 輸出: Bark myD.E(); // 輸出: Dog is eating I myC = new C(); myC.S(); // 輸出: Meow myC.E(); // 輸出: Cat is eating } } ``` **I** 介面定義了兩個方法 **S** 和 **E**。**D** 和 **C** 類實現了 **I** 介面,並提供了這些方法的具體實現。 ## 多重介面繼承 一個類別可以實現多個介面,這在 C# 中的類別繼承中是不允許的(類別只能有一個基類)。 ```C#= interface IFlyable { void Fly(); } interface ISwimmable { void Swim(); } class Duck : IFlyable, ISwimmable { public void Fly() { Console.WriteLine("Duck flying"); } public void Swim() { Console.WriteLine("Duck swimming"); } } class Program { static void Main(string[] args) { Duck duck = new Duck(); duck.Fly(); // 輸出: Duck flying duck.Swim(); // 輸出: Duck swimming } } ``` **Duck** 類同時實現了 **IFlyable** 和 **ISwimmable** 介面,因此必須實現這兩個介面中的所有方法。 ## 隱式和顯式實現 ### 隱式實現 隱式實現介面的成員時,這些成員必須是公有的。 ```C#= interface IExample { void Method(); } class ExampleClass : IExample { // 隱式實現 public void Method() { Console.WriteLine("Implicit implementation"); } } ``` ### 顯式實現 顯式實現介面的成員時,這些成員不必是公有 的,但只能通過介面類型的變量來調用。 ```C#= interface IExample { void Method(); } class ExampleClass : IExample { // 顯式實現 void IExample.Method() { Console.WriteLine("Explicit implementation"); } } class Program { static void Main(string[] args) { IExample example = new ExampleClass(); example.Method(); // 輸出: Explicit implementation } } ``` ### 介面繼承 介面可以繼承自其他介面,從而擴展其功能。 ```C#= interface I { void S(); } interface IPet : I { void Play(); } class D : IPet { public void S() { Console.WriteLine("Bark"); } public void Play() { Console.WriteLine("D is playing"); } } class Program { static void Main(string[] args) { IPet myD = new D(); myD.S(); // 輸出: Bark myD.Play(); // 輸出: Dog is playing } } ``` **IPet** 介面繼承了 **I** 介面,並且新增了一個方法 **Play**。**D** 類實現了 **IPet** 介面,因此必須實現所有從 **I** 和 **IPet** 繼承的方法。 以上是Chapter 7的內容, 製作者:陳彥哲 Email: hanzo010957@gmail.com