C#繼承中的override(重寫)與new(覆蓋)用法

來源:互聯網
上載者:User

標籤:main   不同   不能   區別   ima   err   rri   font   void   

  剛接觸C#編程,我也是被override與new搞得暈頭轉向。於是花了點時間翻資料,看部落格,終於算小有領悟,把學習筆記記錄於此。

  首先聲明一個父類Animal類,與繼承Animal的兩個子類Dog類與Cat類。父類Animal中有一個Say方法,而子類Dog與Cat分別override(重寫)與new(覆蓋)了Say方法。

  讓我們通過執行個體來看一下這兩者有什麼相同與不同之處。

 1     public class Animal 2     { 3         public virtual void Say() 4         { 5             Console.WriteLine("Hello,Animal"); 6         } 7     } 8     public class Dog : Animal 9     {10         public override void Say()11         {12             Console.WriteLine("Hello,Dog");13         }14     }15     public class Cat : Animal16     {17         public new void Say()18         {19             Console.WriteLine("Hello,Cat");20         }21     }

首先說override與new的共同點:

  1. 都是子類在重新實現父類中簽名相同的方法時使用。
  2. 當聲明一個子類對象時,調用這個方法,調用的都是子類中實現的方法。

    例如:

 1 class Program 2     { 3         static void Main(string[] arge) 4         { 5             Dog d = new Dog(); 6             Cat c = new Cat(); 7             d.Say();//調用override的方法 8             c.Say();//調用new的方法 9         }10     }

   輸出是:

Hello,DogHello,Cat

    此時調用的分別是Dog與Cat類中實現的Say方法。

  3.都不會影響父類自身的方法。

   如:

1 class Program2     {3         static void Main(string[] arge)4         {5             Animal a = new Animal();6             a.Say();//調用父類方法。未受影響。7         }8     }

  此時的輸出是:

Hello,Animal

 

下面說兩者的不同之處:

  1.

  (1)override:父類方法必須用virtual修飾,表示這個方法是虛方法,可以被重寫。否則不能被重寫。

  (2)new :   父類方法不必使用virtual修飾。

  2.

  (1)override : 使用override時,父類中必須存在簽名完全相同的virtual方法。否則編譯不通過。

    如果我在Dog類的Say增加一個string類型的形參,則編譯器會提示:沒有合適的方法可以重寫。

  (2)new :   使用new時,父類中最好存在簽名相同的方法。如果沒有,VS會有提示,但編譯不會報錯。此時,new關鍵字便沒有了意義。

   如果我在Cat類的Say增加一個string類型的形參,VS會提示:new關鍵字不是必須的。

  3.當子類中存在與父類方法簽名相同的方法,而沒有被override或new修飾時,預設為new。

  也就是說,override必須寫,而new可以不寫(不推薦)。

  4.這是最重要的一點。以上三點都是使用方法的區別,而這一點是兩者在實際使用時效果的區別。

  (1)override :重寫後,當子類對象轉換為父類時,無法訪問被重寫的虛方法。也就是,被子類重寫後,虛方法在這個子類中便失效了。

   如:

class Program    {        static void Main(string[] arge)        {            Dog d = new Dog();            Animal a = d as Animal;//子類轉換為父類。注意此時a與d指向同一對象,但d是作為Dog類訪問,而a是作為Animal類訪問            d.Say();//此時調用的是override的方法            a.Say();//此時調用的也是override的方法        }    }

    輸出為:

Hello,DogHello,Dog

  兩次調用的都是Dog中重寫的Say方法

  (2)new : 覆蓋後,當子類對象轉換為父類,可以訪問被覆蓋的父類方法。也就是,轉換為父類後,子類new的方法便失效了,此時調用的是父類方法。
       當其再轉換為子類時,調用的又變為子類方法。

    如:

 1 class Program 2     { 3         static void Main(string[] arge) 4         { 5             Cat c = new Cat(); 6             Animal a = c as Animal;//子類轉換為父類。注意此時a與c指向同一對象,但c是作為Cat類訪問,而a是作為Animal類訪問 7             c.Say();//此時調用的是new的方法 8             a.Say();//此時調用的是父類中的方法 9         }10     }

   此時的輸出為:

Hello,CatHello,Animal

記憶體原理:
  我們都知道,調用對象的方法,實際上是訪問對象方法在記憶體中的地址。那麼既然可以通過c.Say()訪問到父類的方法,說明在對象c中,也有Animal類的Say方法。
  事實上,當子類繼承父類的時候,父類中所有方法、欄位(包括私人的)都會複製一份放在子類中。而我們所謂的重寫和覆蓋,重寫、覆蓋的是存放在子類中的,複製出來的方法,而不是父類中的方法,所以當然不會對父類產生任何影響。而不能調用私人的、或者被重寫的方法或欄位,是由於無權訪問,而不是記憶體中不存在。

C#繼承中的override(重寫)與new(覆蓋)用法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.