iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 12
0
自我挑戰組

C# 從入門到WebApi系列 第 12

[Day12] 論物件導向三本柱之二(繼承)

  • 分享至 

  • xImage
  •  

關於繼承

繼承可讓您建立新的類別,以重複使用、擴充和修改其他類別中定義的行為
成員被繼承的類別稱為「基底類別」(父類別)
而繼承這種成員的類別即稱為「衍生類別」(子類別)

繼承最主要個功用正如上方粗體字
為的是增加"重用性"
C#不支援多重繼承
意即一個子類別只能有一個父類別
一個人只能有一個爸爸
C++則支援多重繼承(某天你會發現隔壁老王也是你爸爸)

繼承有遞移性
例如B繼承A C繼承B 則C也能使用A的東東

但是C#支援多重實作
(本篇不講介面Inferface,會放在後兩天的文章中)

如何使用繼承

這時候就要拿出繼承範例中最常被提到Animal類別了(還有shape)

我們先來定義動物的行為和屬性吧
Animal.cs

using System;

namespace Inheritance
{
    public class Animal
    {
        protected string Name;

        public void Move()
        {
            Console.WriteLine("Walk");
        }

        public void GetName()
        {
            Console.WriteLine($"動物的名字是{Name}");
        } 
    }
}

我們宣告了一個protect的欄位Name
這個欄位只有父類別(Animal)和繼承Animal的子類別能使用
另外宣告了兩個public的方法
Move()跟GetName

那我們現在讓狗狗來繼承動物類別吧
Dog.cs

namespace Inheritance
{
    public class Dog : Animal
    {
        public Dog()
        {
            Name = "Dog";
        }
        public void WagTail()
        {
            Console.WriteLine($"{Name}搖了搖尾巴");
        }
    }
}

我們使用 ":"來繼承(實作也是)
裡面只有一個建構式是把Name設為Dog
跟一個搖尾巴的方法

讓我們來看看Main
Program.cs

namespace Inheritance
{
    class Program
    {
        static void Main(string[] args)
        {
            Dog dog = new Dog();
            dog.GetName();
        }
    }
}
//動物的名字是Dog

太神奇了吧傑克
明明狗狗類別裡沒有GetName()
但是卻能使用GetName()
這就是繼承的威力

virtual, Override

現在讓我們來看看小鳥
小鳥一樣有Move的功能
也有GetName()的方法
所以我們讓小鳥繼承Animal的類別

修但幾類
我們仔細看看Animal 中的 Move()方法
他是用Walk來形容移動
可是我鳥鳥明明就是用飛的
當然你也可以幫鳥鳥宣告一個fly方法讓他飛
但是鳥鳥這時候就用不到move方法了
讓他繼承animal就有點沒意義了
所以我們來改寫一下Animal的Move方法

public virtual void Move()
{
     Console.WriteLine("Walk");
}

我們在void前面加上"virtual"關鍵字
代表這個方法是可以被子類別覆寫(override)的

那來看看鳥鳥吧
Bird.cs

using System;

namespace Inheritance
{
    public class Bird:Animal
    {
        public Bird()
        {
            Name = "Bird";
        }

        public override void Move()
        {
            Console.WriteLine("這樣太危險,我飛太遠");
        }
    }
}

我們使用"override"關鍵字來重寫鳥鳥的Move方法

來看看Main吧
為了比較我也讓狗狗移動了一下
Program.cs

using System;

namespace Inheritance
{
    class Program
    {
        static void Main(string[] args)
        {
            Dog dog = new Dog();
            Bird bird = new Bird();
            Console.Write("Dog Move:");
            dog.Move();
            Console.Write("Bird Move:");
            bird.Move();
        }
    }
}

輸出
https://ithelp.ithome.com.tw/upload/images/20200912/20109549lOoF173Xzx.png

如此如此 一般一般
鳥鳥就飛起來了

abstract

顧名思義就是抽象
也就是不具體的
意即指宣告但不進行實作
使用"abstract"關鍵字
繼承抽象類別必須實作所有的抽象方法 否則編譯器會報錯

請看範例
我們將Animal 類別改成抽象類別
並且新增一個抽象方法Eat()

using System;

namespace Inheritance
{
    public abstract class Animal
    {
        protected string Name;

        public virtual void Move()
        {
            Console.WriteLine("Move");
        }

        public void GetName()
        {
            Console.WriteLine($"動物的名字是{Name}");
        }

        public abstract void Eat();
    }
}

抽象方法只能宣告在抽象類別裡
因為鳥鳥跟狗狗都繼承自animal
所以他們必須要實作Eat()方法
使用override 進行實作
Dog.cs

using System;

namespace Inheritance
{
    public class Dog : Animal
    {
        public Dog()
        {
            Name = "Dog";
        }

        public void WagTail()
        {
            Console.WriteLine($"{Name}搖了搖尾巴");
        }

        public override void Eat()
        {
            Console.WriteLine($"{Name}吃肉");
        }
    }
}

Bird.cs

using System;

namespace Inheritance
{
    public class Bird:Animal
    {
        public Bird()
        {
            Name = "Bird";
        }

        public override void Move()
        {
            Console.WriteLine("這樣太危險,我飛太遠");
        }

        public override void Eat()
        {
            Console.WriteLine($"{Name}吃蟲");
        }
    }
}

使用抽象的好處

這個部分就是偏向"設計"的概念
因為還沒有講到ISP(介面隔離原則)
事實上我們在設計一個系統的時候
應該要針對抽象而不是實作
這樣能夠降低耦合性
能夠提升系統的靈活度

我知道正常人看完都是一頭霧水
因為我也是
這部分感覺要實際看過一些實作的系統成能夠理解
不過會接觸到這部份的人應該也不用看這篇了XDD


上一篇
[Day11] 論物件導向三本柱之一(封裝)
下一篇
[Day13] 論物件導向三本柱之三(多形)
系列文
C# 從入門到WebApi30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言