C# 繼承(Inheritance)(Y)

  • 10495
  • 0
  • C#
  • 2021-08-19

利用簡單的例子講解繼承概念

繼承

繼承是物件導向的重要概念,當在無法更動情況下,想要擴充使用者功能時便可使用到繼承(Inheritance)

例如 : 鳥會飛、呼吸,飛機也會飛但不會呼吸,此時我們可將飛設為共同方法,使得鳥的類別跟飛機類別繼承飛這個方法,這樣就不會產生飛機這個類別有飛跟呼吸兩種方法,因為飛機不會呼吸而覺得很奇怪

namespace ConsoleApplication1
{

    public class Fly
    {
        public int speed;

        public void s()
        {
            Console.WriteLine("時速" + speed);

        }
    }

    class AirPlane : Fly
    {
        public string name;
        public string type;

        public void Info()
        {
            Console.WriteLine("飛機型號" + type + "飛機名稱" + name);
        }

        static void Main(string[] args)
        {
            AirPlane c = new AirPlane();
            c.type = "Jstar";
            c.name = "kiki";
            c.speed = 300;

            c.Info();
            c.s();
        }

     
    }

}

這時我們重建方案,利用啟動但不偵錯的輸出結果可以發現,AirPlane繼承了飛這個方法,因此他可以使用飛類別的方法(s)

最終輸出結果

接下來是繼承且繼承的類別包含建構子,建構子(Constructor),就是用來進行物件初始化的方法。

一般來說,例如飛機類別 繼承 Fly 之後就可以使用Fly所開放出來的東西

那麼如果Airplan 繼承 Fly後,想要對Fly進行初始化的動作,那就需要使用繼承建構子了

在建立物件時我們通常都要有初始化的動作。

當Fly類別有建構子時,程式會自行在衍生類別建構子中加上關鍵字base

即使將這段:base 去除仍可以對Fly類別初始化。

Airplane繼承Fly後便會先初始化Fly的建構子,而印出fly類別初始化

(以下程式碼均有簡化,以要敘述的地方為重)

namespace ConsoleApplication1
{

    public class Fly
    {
        public int speed;
        public string initial;
        public Fly()
        {
             initial = "fly類別初始化";
             Console.WriteLine(initial);
        }
      
    }

    class AirPlane : Fly
    {
        public string name;
        public string type;

        public AirPlane()
        :base()
        { 
        }

        public void Info()
        {
            Console.WriteLine("飛機型號" + type + "飛機名稱" + name);
        }

        static void Main(string[] args)
        {
            AirPlane c = new AirPlane();
            c.type = "Jstar";
            c.name = "kiki";
            c.speed = 300;
            c.Info();
            c.s();
        }
    }
}

但是,若Fly類別為多載建構子則就必須在衍生類別強調是初始化哪個建構子

預設的Fly建構子則會被覆蓋掉

namespace ConsoleApplication1
{

    public class Fly
    {
        public int speed;
        public string initial;
        public Fly()
        {
             initial = "fly類別初始化";
             Console.WriteLine(initial);
        }
        public Fly(string name)
        {
            initial = initial + name;
            Console.WriteLine(initial);
        }
    }

    class AirPlane : Fly
    {
        public string name;
        public string type;

        public AirPlane()
        :base("fly多載")
        { 
        }

        public void Info()
        {
            Console.WriteLine("飛機型號" + type + "飛機名稱" + name);
        }

        static void Main(string[] args)
        {
            AirPlane c = new AirPlane();
            c.type = "Jstar";
            c.name = "kiki";
            c.speed = 300;
            c.Info();            
        }
    }
}

宣告覆載方法

如果基礎類別宣告了一個虛擬方法,則可以透過override去宣告該方法的另一種實作方法,與java的寫法不太一樣。

例如:

當我們在fly類別增加了一個叫做flyToString的方法,我們希望可以再衍生類別中呼叫基礎類別(fly)的相同方法,則可使用base

namespace ConsoleApplication1
{

    public class Fly
    {
        public int speed;
        public string initial;
        public Fly()
        {
             initial = "fly類別初始化";
             Console.WriteLine(initial);
        }
        public Fly(string name)
        {
            initial = initial + name;
            Console.WriteLine(initial);
        }

        public virtual void flyToString()
        {
            Console.WriteLine("這是fly原本的string方法");
        }

    }

    class AirPlane : Fly
    {
        public string name;
        public string type;

        public AirPlane()
        :base("fly多載")
        { 
        }
        public override void flyToString()
        {
            base.flyToString();
            //Console.WriteLine("這是airPlaneToString方法");
        }
 

        public void Info()
        {
            Console.WriteLine("飛機型號" + type + "飛機名稱" + name);
        }

        static void Main(string[] args)
        {
            AirPlane c = new AirPlane();
            c.type = "Jstar";
            c.name = "kiki";
            c.speed = 300;
            c.flyToString();
            c.Info();
            c.s();
        }
    }
}

若想要覆蓋本來的方法則必須要在基礎類別要覆蓋的方法前加上Virtual 關鍵字,且衍生類別的方法要在前方加上override,不然在執行程式時,會出現定義不清的警訊

例如:(以下簡化其他程式碼,與上方相同)

 class AirPlane : Fly
    {
        public string name;
        public string type;

        public AirPlane()
        :base("fly多載")
        { 
        }
        public override void flyToString()
        {
          
            Console.WriteLine("這是airPlaneToString方法");
        }
        static void Main(string[] args)
        {
            AirPlane c = new AirPlane();
            c.flyToString();
         
        }
    }

從輸出結果便可以看到console的結果為我們寫覆蓋方法的字串

若將

 public override void flyToString()
        {
            base.flyToString();
            Console.WriteLine("這是airPlaneToString方法");
        }

兩者都寫在ovrride的方法中則是先呼叫基礎類別方法再將其覆蓋成後來的方法