1. 程式人生 > >C#中virtual和abstract的區別

C#中virtual和abstract的區別

tool 保留 到你 variable var 入口 printf static write

解讀一

c# 中 Abstract和Virtual比較容易混淆,都與繼承有關,並且涉及override的使用。下面討論一下二者的區別:

一、Virtual方法(虛方法)

  virtual 關鍵字用於在基類中修飾方法。virtual的使用會有兩種情況:

  情況1:在基類中定義了virtual方法,但在派生類中沒有重寫該虛方法。那麽在對派生類實例的調用中,該虛方法使用的是基類定義的方法。

  情況2:在基類中定義了virtual方法,然後在派生類中使用override重寫該方法。那麽在對派生類實例的調用中,該虛方法使用的是派生重寫的方法。

二、Abstract方法(抽象方法)

abstract關鍵字只能用在抽象類中修飾方法

,並且沒有具體的實現。抽象方法的實現必須在派生類中使用override關鍵字來實現。

接口和抽象類最本質的區別:抽象類是一個不完全的類,是對對象的抽象,而接口是一種行為規範。


三、關鍵字

Static:當一個方法被聲明為Static時,這個方法是一個靜態方法,編譯器會在編譯時保留這個方法的實現。也就是說,這個方法屬於類,但是不屬於任何成員,不管這個類的實例是否存在,它們都會存在。就像入口函數Static void Main,因為它是靜態函數,所以可以直接被調用。

Virtua:當一個方法被聲明為Virtual時,它是一個虛擬方法,直到你使用ClassName variable = new ClassName();聲明一個類的實例之前,它都不存在於真實的內存空間中。這個關鍵字在類的繼承中非常常用,用來提供類方法的多態性支持。

overrride:表示重寫 這個類是繼承於Shape類
virtual,abstract是告訴其它想繼承於他的類 你可以重寫我的這個方法或屬性,否則不允許。
abstract:抽象方法聲明使用,是必須被派生類覆寫的方法,抽象類就是用來被繼承的;可以看成是沒有實現體的虛方法;如果類中包含抽象方法,那麽類就必須定義為抽象類,不論是否還包含其他一般方法;抽象類不能有實體的。

a) virtual修飾的方法必須有方法實現(哪怕只有一對大括號),abstract修飾的方法不能有實現。

b) virtual可以被子類重寫,abstract必須被子類重寫

c) 如果類中的某一函數被abstact修飾,則類名也必須用abstact修飾

d) Abstract修飾的類不能被創建實例。

e) C#中如果準備在子類重寫父類的方法,則該方法在父類中必須用virtual修飾,在子類中必須用overide修飾,避免了程序員在子類中不小心重寫了父類父類方法。

註:用abstract修飾的類只能被繼承不能夠被實例化。

解讀二

virtual和abstract都是用來修飾父類的,通過覆蓋父類的定義,讓子類重新定義。

它們有一個共同點:如果用來修飾方法,前面必須添加public,要不然就會出現編譯錯誤:虛擬方法或抽象方法是不能私有的。畢竟加上virtual或abstract就是讓子類重新定義的,而private成員是不能被子類訪問的。

但是它們的區別很大。(virtual是“虛擬的”,abstract是“抽象的").

(1)virtual修飾的方法必須有實現(哪怕是僅僅添加一對大括號),而abstract修飾的方法一定不能實現。如對於virtual修飾的方法如果沒有實現:

public class Test1
        {
            public virtual void fun1();
        }

錯誤:“Test1.fun1()”必須聲明主體,因為它未標記為 abstract、extern 或 partial

對於abstract修飾的方法如果有實現:

public abstract class Test2
        {
            public abstract void fun2() { }
        }

錯誤: “Test2.fun2()”無法聲明主體,因為它標記為 abstract

(2)virtual可以被子類重寫,而abstract必須被子類重寫。

技術分享圖片
class BaseTest1
    {
       public virtual void fun() { }//必須有實現
    }
    class DeriveTest1:BaseTest1
    {
        //public override void fun() { }
    }
技術分享圖片

編譯不會出現錯誤,如果重寫了virtual修飾的方法,前面必須添加override(這樣就告訴了編譯器你要重寫虛擬方法),而且必須有實現,否則編譯出錯:

技術分享圖片
abstract class BaseTest2
    {
        public abstract void fun();
    }
    class DeriveTest2 : BaseTest2
    {
        //public override void fun();錯誤1:沒有實現
        //public  void fun() { }  錯誤2:重寫時沒有添加override
        //override void fun() { }錯誤3:虛擬成員或者抽象成員不能是私有的(只要在父類中聲明了虛擬成員或抽象成員,即便是繼承的也要加上這個限制)
        public override void fun() { }//如果重寫方法; 錯誤:“A.DeriveTest2”不實現繼承的抽象成員“A.BaseTest2.fun()”    

    }
技術分享圖片

(3)如果類成員被abstract修飾,則該類前必須添加abstract,因為只有抽象類才可以有抽象方法。

(4)無法創建abstract類的實例,只能被繼承無法實例化,比如: BaseTest2 base2 = new BaseTest2();將出現編譯錯誤:抽象類或接口不能創建實例。

(5)C#中如果要在子類中重寫方法,必須在父類方法前加virtual,在子類方法前添加override,這樣就避免了程序員在子類中不小心重寫了父類方法。

(6)abstract方法必須重寫,virtual方法必須有實現(即便它是在abstract類中定義的方法)。

技術分享圖片
abstract public class Test
        {
            //public virtual void Prinf();錯誤:virtual方法必須有實現
            public virtual void Prinf() //abstract類的virtual方法可以不重寫;abstract方法必須重寫。
            {
                Console.WriteLine("Abstract Printf...");
            }

        }
        public class Class1 : Test
        {
            /*
            public override void Prinf() //派生類中不重寫abstract類的virtual方法照樣可以運行,不過調用派生類對象的Printf方法時,調用的是父類的。
            {

                Console.WriteLine("Class One Override Printf...");
            }
             */
        }
技術分享圖片

C#中virtual和abstract的區別