2016年7月11日 星期一

[C#]virtual, abstract, new, override有什麼不同?

一、用途

C#中有virtual, abstract, new, override四個關鍵字用來管理類別繼承時函數的覆寫關係。

二、virtual, abstract, new, override四種關鍵字的比較表

關鍵字 中文 使用類別 說明
virtual 虛擬方法 父類別 宣告方法且實作,預期子類別會覆寫
abstract 抽象方法 父類別 只宣告方法不實作
new 覆寫方法 子類別 覆寫父類別宣告的方法
override 覆寫方法 子類別 覆寫父類別宣告的方法

三、可能的狀況


狀況 父類別 子類別 說明
1 無關鍵字 無覆寫 子類別繼承父類別的方法。
2 無關鍵字 new 當子類別要覆寫父類別但父類別沒有關鍵字時,只能以new覆寫,如要使用override,就要將父類別設成virtual。
3 virtual 無覆寫 子類別繼承父類別的方法。
4 virtual new 子類別覆寫父類別方法
5 virtual override 子類別覆寫父類別方法
6 abstract override 當父類別有抽象類別時,子類別都必須要用override實作。

四、virtual, abstract, new, override的例子

狀況2,如下例
class ParentClass{        
    public void no(){            
        Console.WriteLine( "I'm parent no class");        
    }
}
class ChildClass:ParentClass
{
    public new void no()
    {
        Console.WriteLine("I'm Child no class");
    }
}
class Program
{
    static void Main(string[] args)
    {
        ParentClass p = new ParentClass();
        p.no();
        ParentClass c = new ChildClass();
        c.no();
    }
}
執行結果是:
I'm parent no class
I'm Child no class

表示可以在子類別ChildClass中使用new關鍵字來覆寫在父類別無關鍵字的no方法。

狀況4和5,如下例
class ParentClass
{
    public virtual void virtualF() {
        Console.WriteLine("I'm parent virtual class");
    }
    public virtual void virtual2F()
    {
        Console.WriteLine("I'm parent virtual2 class");
    }
}
class ChildClass:ParentClass
{
     public override void virtualF()
    {
        Console.WriteLine("I'm Child virtual override class");
    }
    public new void virtual2F()
    {
        Console.WriteLine("I'm Child virtual 2 new class");
    }
}
class Program
{
     
     static void Main(string[] args)
    {
        ParentClass p = new ParentClass();
        p.virtualF();
        p.virtual2F();         
  ChildClass c = new ChildClass();
        ParentClass pc = new ChildClass();
        c.virtualF();
        c.virtual2F();
        pc.virtualF();
        pc.virtual2F();         

         
    }
}
執行結果是:
I'm parent virtual class
I'm parent virtual2 class
I'm Child virtual override class
I'm Child virtual 2 new class
I'm Child virtual override class
I'm parent virtual2 class
首先,物件c和pc都是ChildClass生成,但是pc是作為父類別ParentClass來使用。
virtualF() 使用override:
c.virtualF()和pc.virtualF()都會輸出I'm Child virtual override class
代表無論物件以子類別或父類別來使用,override時,都會採用子類別所定義的方法。
virtual2F() 使用new:
c.virtual2F()會輸出I'm Child virtual 2 new class
pc.virtual2F()會輸出I'm parent virtual2 class
代表物件以子類別來使用時會採用子類別所定義的方法,物件以父類別來使用時會採用父類別所定義的方法。
結論是override把原方法砍掉重練(再也無法使用父類別方法),而new只是定義新方法,但仍會保留原來的方法,要使用父類別方法就宣告成父類別,要使用子類別方法就宣告成子類別。
狀況6,如下例
abstract class AbstractClass
{
 public void no()
 {
  Console.WriteLine("I'm abstract no class");
 }
 public abstract void abstractF();
}
class childClass2 : AbstractClass
{
 public override void abstractF()
 {
  Console.WriteLine("I'm childClass2 abstract override class");
 }
}
class Program
{
 
  static void Main(string[] args)
 {
  childClass2 c2 = new childClass2();
  c2.no();
  c2.abstractF();
 }
}
執行結果是:
I'm abstract no class
I'm childClass2 abstract override class
所謂的abstract method就像例子中的abstractF,只有宣告沒有實作。
如果class中有一個abstract method,class就要設成abstract class,而abstract class 不能直接物件化,必須要有子類別去繼承abstract class並覆寫(override)所有的abstract method。

沒有留言:

張貼留言