2026-05-22 C#接口與抽象類練習題解答

2026-05-22 C#接口與抽象類練習題解答

我:
第七階段練習的答案:
using System;
using System.Collections;
using System.ComponentModel.Design;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;

class Program
#region 練習 1:定義和實現接口
{ //練習 1:定義和實現接口
public interface IVehicle
{
public void Start();
public void Stop();
}

public class Car : IVehicle
{
    public void Start()
    {
        Console.WriteLine("Car Starting.....");
    }

    public void Stop()
    {
        Console.WriteLine("Car Stopping....");
    }
}

    public class  Bicycle : IVehicle 
    {
        public void Start()
         {
              Console.WriteLine("Bike Starting....");
         }
        public void Stop()
        {
            Console.WriteLine("Bike Stopping...");
        }
    }
#endregion

#region 練習 2:使用抽象類
public abstract class Appliance()
{
    public abstract void TurnOn();
    public void TurnOff()
    {
        Console.WriteLine("Turning off appliance...");
    }
}

public class WashingMachine : Appliance
{
    public override void TurnOn()
    {
        Console.WriteLine("Turning on WashingMachine");
    }
}
#endregion

#region 練習 3:結合接口和抽象類
public interface IPlayable
{
    public void play(); 
}

public abstract class Instrument
{
    public abstract void Tune();
}

public class Guiter : Instrument, IPlayable
{
    public override void Tune() {
        Console.WriteLine("Tuning Guiter");
    }
    public void play()
    {
        Console.WriteLine("play Guiter");
    }

}
#endregion
static void Main(string[] args)
{
    #region  練習 1:定義和實現接口
    //練習 1:定義和實現接口
    Car myCar = new Car();
    myCar.Start();
    myCar.Stop();

    Bicycle myBicycle = new Bicycle();  
    myBicycle.Start();  
    myBicycle.Stop();
    #endregion

    #region 練習 2:使用抽象類
    WashingMachine myWashingMachine = new WashingMachine();
    {
        myWashingMachine.TurnOn();
        myWashingMachine.TurnOff();
    }
    #endregion

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

    Guiter myGuiter = new Guiter();
    myGuiter.Tune();
    myGuiter.play();

    #endregion
}

}
問題

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

    1. 接口(interface) 就是當多個類別需要實作同一個方法, 可將它提出來作一個接口.
      比如 人事薪資系統: 員工的類別有 正式員工、約聘員工、工讀生、實習生, 每類的員工都需要計自薪資,
      於是將計算薪資這個方法提出來一個接口 ICalculate , 然後有一個實作方法叫 getSalary(),
      每一類員工(PermanentEmployee 、ParttimeEmployee…)都須實作getSalary() 這個方法.
      但可能只有正式員工或是工讀生、實習生可加勞保、健保, 所以可以多設計一個接口勞保 及 健保的接口,
      (ILaborInsurance、IHealthInsurance) 以便加退保.
      2.抽象(abstract) : 就是一種不完整的類, 它會有抽象方法, 由子類去實現,
      比如: 接上 人事薪資系統, 會有一些共同的員工資料, 比如 姓名、姓別、國家別、生日…等,這些為共通屬性,
      但會依照不同員工類有不同的薪資計算方法,
      就可以設計一個抽象方法 getSalary()由字類去實作.
  2. 問題 2:為什麼 C# 中允許一個類實現多個接口,但只能繼承一個抽象類
    答案:
    如果 C# 允許多個基類,那麼類之間的繼承層級會變得非常複雜。例如,如果兩個基類中都有同名的方法或屬性,
    則衝突會使得子類無法確定應該使用哪個基類的方法或屬性,這稱為菱形繼承問題。
    為了避免這些複雜性,C# 僅允許一個抽象基類,從而維持清晰的繼承層級,讓子類僅繼承單一父類的成員和實現。

  3. 問題 3:如果一個類需要具有多種不同的行為(例如會飛和會游泳),應該如何設計類的結構以保持靈活性並降低耦合?
    答案:
    可以設計二個Interface,一個 IFly , 裏面有一個 canFly() 的方法,
    一個ISwimming , 裏面有一個 canSwim() 的方法.
    然後由這個類繼承實作這二個方法.

GPT:
你的程式碼結構和練習解答寫得非常清晰!也對接口與抽象類的應用解釋得很完整。以下是一些小修改建議和補充回答,以便加深理解:


程式碼優化建議

  1. **抽象類 Appliance**:

    • 定義抽象類時,不需要在後面加上括號。
    • 使用 TurnOnTurnOff 表現了家電的基本行為,保持了抽象類別在行為擴展上的優勢。
  2. 接口的命名

    • Guiter 應該更正為 Guitar
    • 方法名通常建議以大寫開頭以符合 C# 命名慣例,例如將 play() 改為 Play()

問題解答補充

問題 1:接口與抽象類的主要區別是什麼?
補充說明

  • 接口主要是為了定義一組行為契約,強調功能,通常用於橫向擴展功能。而抽象類則是為了提供基礎結構,並允許繼承。選擇使用抽象類還是接口,關鍵在於看是否有共享的具體實現需求。

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

  • 接口不包含具體實現,無法直接造成資源衝突,因此 C# 允許多接口實現。
  • 抽象類可能含有已實現的方法與屬性,允許多重繼承會導致資源衝突,增加維護難度,因此 C# 避免多重繼承的複雜性。

問題 3:如果一個類需要具有多種不同的行為,如何保持靈活性並降低耦合?
補充說明

  • 設計多個接口讓類別可以選擇性實現不同行為,這是一種組合優於繼承的原則應用。