類的虛擬方法與多態

首先理解一下什麼叫多態。同一操作作用於不同的對象,可以有不同的解釋,產生不同的執行結果,這就是多態性。

多態性通過派生類覆寫基類中的虛函數型方法來實現。

 

多態性分爲兩種,一種是編譯時的多態性,一種是運行時的多態性。

編譯時的多態性:編譯時的多態性是通過重載來實現的。對於非虛的成員來說,系統在編譯時,根據傳遞的參數、返回的類型等信息決定實現何種操作。

運行時的多態性:運行時的多態性就是指直到系統運行時,才根據實際情況決定實現何種操作。C#中運行時的多態性是通過覆寫虛成員實現。
下面我們來分別說明一下多態中涉及到的四個概念:重載,覆寫,虛方法和抽象方法。

重載和覆寫的區別:

重載

類中定義的方法的不同版本

         public int Calculate(int x, int y)

         public double Calculate(double x, double y)

特點(兩必須一可以)

         方法名必須相同

         參數列表必須不相同

         返回值類型可以不相同

覆寫

         子類中爲滿足自己的需要來重複定義某個方法的不同實現。

         通過使用override關鍵字來實現覆寫。

         只有虛方法和抽象方法才能被覆寫。

         要求(三相同)

                   相同的方法名稱

                   相同的參數列表

                   相同的返回值類型

 

最後再來介紹一下虛方法和抽象方法

虛方法

聲明使用virtual關鍵字。

調用虛方法,運行時將確定調用對象是什麼類的實例,並調用適當的覆寫的方法。

虛方法可以有實現體。

抽象方法

必須被派生類覆寫的方法。

可以看成是沒有實現體的虛方法。

如果類中包含抽象方法,那麼類就必須定義爲抽象類,不論是否還包含其他一般方法。

 

多態

面向對象的語言使用虛方法表達多態。這就意味着派生類可以有和父類具有同樣簽名的方法,並且父類可以調用派生類的方法【譯註:此處應該是對象(或對象引用、指向對象的指針)】。在Java中,缺省情況下方法就是虛的。在C#中,必須使用virtual關鍵字才能使方法被父類調用。

在C#中,還需要override關鍵字以指明一個方法將重載(或實現一個抽象方法)其父類的方法。

Class B //【譯註:應爲class B】

{

public virtual void foo () {}

}

Class D : B //【譯註:應爲class D : B】

{

public override void foo () {}

}

試圖重載一個非虛的方法將會導致一個編譯時錯誤,除非對該方法加上“new”關鍵字,以指明該方法意欲隱藏父類的方法。

Class N : D //【譯註:應爲class N : D】

{

public new void foo () {}

}

N n = new N ();

n.foo(); // 調用N的foo

((D)n).foo(); // 調用D的foo

((B)n).foo(); // 調用D的foo

和C++、Java相比,C#的override關鍵字使得閱讀源代碼時可以清晰地看出哪些方法是重載的。不過,使用虛方法有利有弊。第一個有利點是:避免使用虛方法輕微的提高了執行速度。第二點是可以清楚地知道哪些方法會被重載。

【譯註:從“不過”至此,這幾句話顯然不合邏輯,但原文就是如此:

  “However, requiring the use of the virtual method has its pros and cons. The first pro is that is the slightly increased execution speed from avoiding virtual methods. The second pro is to make clear what methods are intended to be overridden.”。

  我認爲,若將被我標爲斜體的method改爲keyword的話,邏輯上會順暢些。這樣,第一句話就可認爲是和Java比,因其方法缺省是虛的,第二句話主要是和C++比】。然而,利也可能是弊。和Java中缺省忽略final修飾符

【譯註:在Java中可利用final關鍵字,對方法上鎖,相當於C#/C++中沒有用virtual關鍵字修飾方法/成員函數的情況】以及C++中缺省忽略virtual修飾符相比,Java中缺省選項

【譯註:即虛的】使得你程序略微損失一些效率,而在C++中,它可能妨礙了擴展性,雖然這對基類的實現者來說,是不可預料的。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章