C# 多態的實現

來源:互聯網
上載者:User

標籤:jpg   地方   個人   應用   定義   但我   物件導向   lin   方法   

封裝、繼承、多態,物件導向的三大特性,前兩項理解相對容易,但要理解多態,特別是深入的瞭解,對於初學者而言可能就會有一定困難了。我一直認為學習OO的最好方法就是結合實踐,封裝、繼承在實際工作中的應用隨處可見,但多態呢?也許未必,可能不經意間用到也不會把它跟“多態”這個詞對應起來。在此拋磚引玉,大家討論,個人能力有限,不足之處還請指正。
之前看到過類似的問題:如果面試時主考官要求你用一句話來描述多態,儘可能的精鍊,你會怎麼回答?當然答案有很多,每個人的理解和表達不盡相同,但我比較趨向這樣描述:通過繼承實現的不同對象調用相同的方法,表現出不同的行為,稱之為多態。

例1:

代碼 
public class Animal    {        public virtual void Eat()        {            Console.WriteLine("Animal eat");        }    }    public class Cat : Animal    {        public override void Eat()        {            Console.WriteLine("Cat eat");        }    }    public class Dog : Animal    {        public override void Eat()        {            Console.WriteLine("Dog eat");        }    }    class Tester    {        static void Main(string[] args)        {            Animal[] animals = new Animal[3];            animals[0] = new Animal();            animals[1] = new Cat();            animals[2] = new Dog();            for (int i = 0; i < 3; i++)            {                animals[i].Eat();            }        }    }

輸出如下:

Animal eat...

Cat eat...

Dog eat...

在上面的例子中,通過繼承,使得Animal對象數組中的不同的對象,在調用Eat()方法時,表現出了不同的行為。

多態的實現看起來很簡單,要完全理解及靈活的運用c#的多態機制,也不是一件容易的事,有很多需要注意的地方。

 

1. new的用法

先看下面的例子。

例2

 

代碼 
public class Animal    {        public virtual void Eat()        {            Console.WriteLine("Animal eat");        }    }    public class Cat : Animal    {        public new void Eat()        {            Console.WriteLine("Cat eat");        }    }    class Tester    {        static void Main(string[] args)        {            Animal a = new Animal();            a.Eat();            Animal ac = new Cat();            ac.Eat();            Cat c = new Cat();            c.Eat();        }    }

運行結果為:

Animal eat...

Animal eat...

Cat eat...

可以看出,當衍生類別Cat的Eat()方法使用new修飾時,Cat的對象轉換為Animal對象後,調用的是Animal類中的Eat()方法。其實可以理解為,使用new關鍵字後,使得Cat中的Eat()方法和Animal中的Eat()方法成為毫不相關的兩個方法,只是它們的名字碰巧相同而已。所以, Animal類中的Eat()方法不管用還是不用virtual修飾,也不管存取權限如何,或者是沒有,都不會對Cat的Eat()方法產生什麼影響(只是因為使用了new關鍵字,如果Cat類沒用從Animal類繼承Eat()方法,編譯器會輸出警告)。

 

我想這是設計者有意這麼設計的,因為有時候我們就是要達到這種效果。嚴格的說,不能說通過使用new來實現多態,只能說在某些特定的時候碰巧實現了多態的效果。

 

 

2.override實現多態

真正的多態使用override來實現的。回過去看前面的例1,在基類Animal中將方法Eat()用virtual標記為虛擬方法,再在衍生類別Cat和Dog中用override對Eat()修飾,進行重寫,很簡單就實現了多態。需要注意的是,要對一個類中一個方法用override修飾,該類必須從父類中繼承了一個對應的用virtual修飾的虛擬方法,否則編譯器將報錯。

 

好像講得差不多了,還有一個問題,不知道你想沒有。就是多層繼承中又是怎樣實現多態的。比如類A是基類,有一個虛擬方法method()(virtual修飾),類B繼承自類A,並對method()進行重寫(override修飾),現在類C又繼承自類B,是不是可以繼續對method()進行重寫,並實現多態呢?看下面的例子。

 

例3:

 

代碼 
public class Animal    {        public virtual void Eat()        {            Console.WriteLine("Animal eat");        }    }    public class Dog : Animal    {        public override void Eat()        {            Console.WriteLine("Dog eat");        }    }    public class WolfDog : Dog    {        public override void Eat()        {            Console.WriteLine("WolfDog eat");        }    }    class Tester    {        static void Main(string[] args)        {            Animal[] animals = new Animal[3];            animals[0] = new Animal();            animals[1] = new Dog();            animals[2] = new WolfDog();            for (int i = 0; i < 3; i++)            {                animals[i].Eat();            }        }}

 運行結果為:

Animal eat...

Dog eat...

WolfDog eat... 

在上面的例子中類Dog繼承自類Animal,對方法Eat()進行了重寫,類WolfDog又繼承自Dog,再一次對Eat()方法進行了重寫,並很好地實現了多態。不管繼承了多少層,都可以在子類中對父類中已經重寫的方法繼續進行重寫,即如果父類方法用override修飾,如果子類繼承了該方法,也可以用override修飾,多層繼承中的多態就是這樣實現的。要想終止這種重寫,只需重寫方法時用sealed關鍵字進行修飾即可。

 

 

3. abstract-override實現多態

先在我們在來討論一下用abstract修飾的抽象方法。抽象方法只是對方法進行了定義,而沒有實現,如果一個類包含了抽象方法,那麼該類也必須用abstract聲明為抽象類別,一個抽象類別是不能被執行個體化的。對於類中的抽象方法,可以再其衍生類別中用override進行重寫,如果不重寫,其衍生類別也要被聲明為抽象類別。看下面的例子。

例4:

 

 

代碼 
public abstract class Animal    {      public abstract void Eat();    }    public class Cat : Animal    {        public override void Eat()        {            Console.WriteLine("Cat eat");        }    }    public class Dog : Animal    {        public override void Eat()        {            Console.WriteLine("Dog eat");        }    }    public class WolfDog : Dog    {        public override void Eat()        {            Console.WriteLine("Wolfdog eat");        }    }    class Tester    {        static void Main(string[] args)        {            Animal[] animals = new Animal[3];            animals[0] = new Cat();            animals[1] = new Dog();            animals[2] = new WolfDog();            for (int i = 0; i < animals.Length; i++)            {                animals[i].Eat();            }        }    }

運行結果為:

Cat eat...

Dog eat...

Wolfdog eat...

從上面可以看出,通過使用abstract-override可以和virtual-override一樣地實現多態,包括多層繼承也是一樣的。不同之處在於,包含虛擬方法的類可以被執行個體化,而包含抽象方法的類不能被執行個體化。

以上動圖由“圖鬥羅”提供

C# 多態的實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.