abstractvirtualoverridenew是在類別的繼承關係中常用的四個修飾方法的關鍵字,在此略作總結。

1. 常用的中文名稱:

n   abstract => 抽象方法。

n   virtual => 虛擬方法。

n   override => 覆蓋基礎類別方法。

n   new => 隱藏基礎類別方法。

n   override new 有時都叫覆寫基礎類別方法

2. 適用場合:

n   abstract virtual 用在基礎類別(父類別)

n   override new 用在派()生類別(子類別)中。

3. 具體概念:

n   abstract 抽象方法,是空的方法,沒有方法實體,派()生類必須以 override 實現此方法。

n   virtual 虛擬方法,若希望或預料到基礎類別的這個方法在將來的派()生類別中會被覆寫(override new,則此方法必須被聲明為 virtual

n   override 覆寫繼承自基礎類別的virtural方法,可以理解為拆掉老房子,在原址上建新房子,老房子再也找不到了(基礎類別方法永遠調用不到了)。

n   new 隱藏繼承自基礎類別的virtual方法,老房子還留着,在旁邊蓋個新房子,想住新房子的住新房子(作為衍生類別對象調用),想住老房子住老房子(作為基礎類別對象調用)。

n   當派()生類別中出現與基礎類別同名的方法,而此方法前面未加 override new 修飾符時,編譯器會報警告,但不報錯,真正執行時等同於加了new

3. abstract virtual 的區別:

n   abstract 方法還沒實現,連累着基礎類別也不能被實例化,除了作為一種規則或符號外沒啥用;virtual 則比較好,派()生類別想覆寫就覆寫,不想覆寫就吃老子的。

n   而且繼承再好也是少用為妙,繼承層次越少越好,派()生類別新擴展的功能越少越好,virtual 深合此意。

4. override new 的區別:

n   當派()生類別對象作為基類類型使用時,override 的執行派()生類別方法,new 的執行基礎類別方法。

n   如果作為派()生類別類型調用,則都是執行 override new 之後的。

文章標籤
創作者介紹

吉米.NET

Jimmy 發表在 痞客邦 PIXNET 留言(12) 人氣()


留言列表 (12)

發表留言
  • 悄悄話
  • Jimmy
  • 是可以呀,不過我強調的是概念問題、原意是什麼,你繼承一個base,覆寫他(因該是覺得他不好用或是不想用原本的方法而去覆寫掉),又要呼叫他的舊方法,是因為你要使用base的舊方法沿續做下去嗎?....好像有點怪的用意,要麻就不要用同名方法的然後用base呼叫他比較好,那就沒有覆不覆寫的問題,就是直接call父類別的method用啦~,只是在子類別可以直接用base.XXX(),我是想不到有什麼的情況會一定要用覆寫他的method又要使用舊方法的恰當時機,可以給個意見喔,虛心接受.....
  • 悄悄話
  • 訪客
  • override 覆寫繼承自基礎類別的virtural方法,可以理解為拆掉老房子,在原址上建新房子,老房子再也找不到了(基礎類別方法永遠調用不到了)。

    virtural =>virtual
    ---------------------------------------------------------------------------------------------------------------
    以上是雞蛋挑骨頭,
    謝謝你的講解,
    對初學者的我是一大幫助!
  • 訪客
  • 很棒的觀念=D
  • 廷展 顏
  • override 覆寫繼承自基礎類別的virtural方法,可以理解為拆掉老房子,在原址上建新房子,老房子再也找不到了(基礎類別方法永遠調用不到了)。
    ---------------------------------------------------------------------------------------------------------------

    這會誤導說無法在子類別 先去執行 父類別 裡面的code 吧 (像你說的有base())


    實例:

    在寫.Net WebForm 的時候
    BaseClass 先繼承了 System.Web.UI.Page 去覆寫 OnLoad 事件 (做來源檢查或權限檢查等等的,這時候做完了才會需要去執行本來正常情況 OnLoad 會去執行的事件 (系統內定的)

    這時候

    protected override void OnLoad(EventArgs e)
    {
    //來源檢查或權限檢查


    //檢查通過才去呼叫系統內定的方法
    base.OnLoad(e);
    }
  • 訪客
  • 口氣明明很差
    還虛心接受個屁
    去你媽的

    爛文章刪一刪啦
  • 訪客
  • 我觉得写得清楚又好。不想一些明明是简单的东西非要写的晦涩难懂
  • Molly Chen
  • override 覆寫繼承自基礎類別的virtural方法,可以理解為拆掉老房子,在原址上建新房子,老房子再也找不到了(基礎類別方法永遠調用不到了)。
    --------------------------------------------------------------------------------------------------------
    不能說"永遠"調用不到,應該說基礎類別的 function pointer 其內容會被覆蓋掉

    你可以理解為,加上 virtual 關鍵字後,原本單純的 function() 會變成 function pointer。所有呼叫 function() 的動作都會變成透過 function pointer 去呼叫該 function。
    使用 override 關鍵字,會覆蓋掉父類別的 function pointer 的值,使其 address 指向子類別的 Child.function(),因此所有原本呼叫 function() 的動作就全部變成呼叫 Child.function() 了。
    而使用 base.function() 就是強制指向父類別的 function()。

    而使用 new 關鍵字,就只是單純的建立一個新的且同名的 Child.function(),不會影響任何舊有呼叫父類別 Parent.function() 的動作。

    ------------提供大家virtual、override、new實際的範例程式碼如下,跑跑看,很有趣---------------
    using System;

    namespace Test
    {
    class Program
    {
    static void Main(string[] args)
    {
    Father[] d = { new Father()
    , new Son()
    , new Daughter()
    , new Grandson()
    , new Granddaughter() };
    for (int i = 0; i < 5; i++)
    Console.WriteLine("= " + d[i].Order()); // 編譯後一律呼叫 d->OrderP()
    Console.ReadLine();
    }
    }
    // 使用 virtual 關鍵字將產生 function pointer ,假設其名稱為 OrderP = 0x0001000
    // 而 Order() 的機器碼就會放在 0x0001000 這個位址
    // 呼叫 Order() 的程式碼編譯後變成透過 function pointer 呼叫,也就是 ->OrderP()
    class Father
    {
    public virtual int Order() { Console.Write("Father "); return DateTime.Now.Millisecond; }
    }
    // Compiler 產生新的 function 名為 Son_Order() ,其機器碼被放在 0x0001100 這個位址
    // 而 OrderP 的內容被改為 0x0001100
    // 因此使用 ->OrderP() 會執行 Son_Order()
    class Son : Father
    { // override 的 function 並非永遠找不到,使用 base.FunctionName() 強制指回就可以了
    public override int Order() { Console.Write("Son*2 "); return base.Order() * 2; }
    }
    // 使用 new 產生新的 function,機器碼放在 0x0010100
    // 原本的 OrderP 內容不變,仍為 0x0001000
    // 並產生一個新的 function pointer 名為 Daughter_OrderP = 0x0010100
    // 使用 ->OrderP() 執行原本 Father 的 Order()
    class Daughter : Father
    { // 必須宣告成 virtual,否則子類別 Granddaughter 將判定沒有 function pointer 可覆蓋。
    public virtual new int Order() { Console.Write("Daughter+500 "); return base.Order() + 500; }
    }
    // Compiler 產生新的 Grandson_Order() 放在 0x1001100
    // OrderP 改為 0x1001100,所以 ->OrderP() 會執行 Grandson_Order()
    // 而 base.Order 則指向 Son_Order()
    class Grandson : Son
    {
    public override int Order() { Console.Write("Grandson-10 "); return base.Order() - 10; }
    }
    // Compiler 產生新的 Granddaughter_Order() 放在 0x0011100
    // 並將 Daughter_OrderP 設為 0x0011100 。 OrderP 內容不變,仍為 0x0001000
    // 由於沒有覆蓋到 OrderP ,呼叫 ->OrderP() 是執行 Father 的 Order()
    class Granddaughter : Daughter
    {
    public override int Order() { Console.Write("Granddaughter/2 "); return base.Order() / 2; }
    }

    }
    ------------以上程式碼輸出如下---------------
    Father = 943
    Son*2 Father = 1886
    Father = 943
    Grandson-10 Son*2 Father = 1876
    Father = 943
  • Molly Chen
  • 回2樓,以上範例展示了一種 base 的使用方式,這種情況必須使用 overrride,否則 for loop 那邊就跑不動。
    另一個範例是6樓所說的 OnLoad。若不 override OnLoad,而是弄一個新的 MyLoad,則頁面載入時 MyLoad 根本不會被觸發到。
  • olivermode
  • 感謝整理,大感謝!!
  • Minip
  • 感謝大大文章,簡單明瞭~初學者覺得受用
找更多相關文章與討論