C 多型的理解

2021-07-11 08:45:00 字數 4156 閱讀 3658

本文**msdn    

此 多型性常被視為自封裝和繼承之後,物件導向的程式設計的第三個支柱。 

polymorphism(多型性)是乙個希臘詞,指「多種形態」,多型性具有兩個截然不同的方面:

在執行時,在方法引數和集合或陣列等位置,派生類的物件可以作為基類的物件處理。 

發生此情況時,該物件的宣告型別不再與執行時型別相同。

基類可以定義並實現

虛方法,派生類可以

重寫這些方法,即派生類提供自己的定義和實現。 

在執行時,客戶端**呼叫該方法,clr 查詢物件的執行時型別,並呼叫虛方法的重寫方法。

因此,您可以在源**中呼叫基類的方法,但執行該方法的派生類版本。

虛方法允許您以統一方式處理多組相關的物件。 

例如,假定您有乙個繪圖應用程式,允許使用者在繪圖圖面上建立各種形狀。

您在編譯時不知道使用者將建立哪些特定型別的形狀。

但應用程式必須跟蹤建立的所有型別的形狀,並且必須更新這些形狀以響應使用者滑鼠操作。

您可以使用多型性通過兩個基本步驟解決這一問題:

建立乙個類層次結構,其中每個特定形狀類均派生自乙個公共基類。

使用虛方法通過對基類方法的單個呼叫來呼叫任何派生類上的相應方法。

首先,建立乙個名為 

shape 的基類,並建立一些派生類,例如 

rectangle、

circle 和 

********。 

為 shape 類提供乙個名為 draw 的虛方法,並在每個派生類中重寫該方法以繪製該類表示的特定形狀。

建立乙個 list 物件,並向該物件新增 circle、******** 和 rectangle。

若要更新繪圖圖面,請使用 foreach 迴圈對該列表進行迴圈訪問,並對其中的每個 shape 物件呼叫 draw 方法。

雖然列表中的每個物件都具有宣告型別 shape,但呼叫的將是執行時型別(該方法在每個派生類中的重寫版本)。

c#

public

class shape

public

int y

public

int height

public

int width

// virtual method

public

virtual

void draw()

}class circle : shape

}class rectangle : shape

}class ******** : shape

}class program

// keep the console open in debug mode.

console.writeline("press any key to exit.");

console.readkey();

}}/* output:

drawing a rectangle

performing base class drawing tasks

drawing a ********

performing base class drawing tasks

drawing a circle

performing base class drawing tasks

*/

在 c# 中,每個型別都是多型的,因為包括使用者定義型別在內的所有型別都繼承自 object。

多型性概述

當派生類從基類繼承時,它會獲得基類的所有方法、字段、屬性和事件。 

派生類的設計器可以選擇是否

僅當基類成員宣告為 

virtual 或 

abstract 時,派生類才能重寫基類成員。 

派生成員必須使用 override 關鍵字顯式指示該方法將參與虛呼叫。

以下**提供了乙個示例:

c#

public

class baseclass

public

virtual

int workproperty

}}public

class derivedclass : baseclass

public

override

int workproperty

}}

字段不能是虛擬的,只有方法、屬性、事件和索引器才可以是虛擬的。 

當派生類重寫某個虛擬成員時,即使該派生類的例項被當作基類的例項訪問,也會呼叫該成員。

以下**提供了乙個示例:

c#

derivedclass b = new derivedclass();

b.dowork(); // calls the new method.

baseclass a = (baseclass)b;

a.dowork(); // also calls the new method.

虛方法和屬性允許派生類擴充套件基類,而無需使用方法的基類實現。 

有關更多資訊,請參見 使用 override 和 new 關鍵字進行版本控制(c# 程式設計指南)。

介面提供另一種方式來定義將實現留給派生類的方法或方法集。

有關更多資訊,請參見 介面(c# 程式設計指南)。

如果希望派生成員具有與基類中的成員相同的名稱,但又不希望派生成員參與虛呼叫,則可以使用 

new 關鍵字。 

new 關鍵字放置在要替換的類成員的返回型別之前。

以下**提供了乙個示例:

c#

public

class baseclass

public

int workfield;

public

int workproperty

}}public

class derivedclass : baseclass

public

newint workfield;

public

newint workproperty

}}

通過將派生類的例項強制轉換為基類的例項,仍然可以從客戶端**訪問隱藏的基類成員。 

例如: c#

derivedclass b = new derivedclass();

b.dowork(); // calls the new method.

baseclass a = (baseclass)b;

a.dowork(); // calls the old method.

無論在虛擬成員和最初宣告虛擬成員的類之間已宣告了多少個類,虛擬成員永遠都是虛擬的。 

如果類 a 宣告了乙個虛擬成員,類 b 從 a 派生,類 c 從類 b 派生,則類 c 繼承該虛擬成員,並且可以選擇重寫它,而不管類 b 是否為該成員宣告了重寫。

以下**提供了乙個示例:

c#

public

class a

}public

class b : a

}

派生類可以通過將重寫宣告為 

sealed 來停止虛擬繼承。 

這需要在類成員宣告中的 override 關鍵字前面放置 sealed 關鍵字。

以下**提供了乙個示例:

c#

public

class c : b

}

在上乙個示例中,方法 

dowork 對從 c 派生的任何類都不再是虛擬方法。 

即使它們轉換為型別 b 或型別 a,它對於 c 的例項仍然是虛擬的。

通過使用 new 關鍵字,密封的方法可以由派生類替換,如下面的示例所示:

c#

public

class d : c

}

在此情況下,如果在 d 中使用型別為 d 的變數呼叫 

dowork,被呼叫的將是新的 

dowork。 

如果使用型別為 c、b 或 a 的變數訪問 d 的例項,對 dowork 的呼叫將遵循虛擬繼承的規則,即把這些呼叫傳送到類 c 的 dowork 實現。

已替換或重寫某個方法或屬性的派生類仍然可以使用基關鍵字訪問基類的該方法或屬性。 

以下**提供了乙個示例:

c#

public

class base

}public

class derived : base

}

C 多型的理解

一 什麼是多型 物件導向程式設計中的另外乙個重要概念是多型性。在執行時,可以通過指向基類的指標,來呼叫實現派生類中的方法。可以把一組物件放到乙個陣列中,然後呼叫它們的方法,在這種場合下,多型性作用就體現出來了,這些物件不必是相同型別的物件。當然,如果它們都繼承自某個類,你可以把這些派生類,都放到乙個...

C 多型理解

多型 什麼是多型?其實也可以說是一種介面,多種實現方法。分為靜態多型和動態多型。靜態多型分為函式過載和泛型程式設計,也可以說是靜態聯編,在編譯期間就可以確定了。函式過載主要是函式的引數列表的不同 資料型別的不同和引數個數的不同 泛型程式設計就是建立乙個模板,輸入不同的資料型別也可以實現想要的功能。動...

C 多型理解

封裝 繼承 多型,物件導向的三大特性,前兩項理解相對容易,但要理解多型,特別是深入的了解,對於初學者而言可能就會有一定困難了。我一直認為學習oo的最好方法就是結合實踐,封裝 繼承在實際工作中的應用隨處可見,但多型呢?也許未必,可能不經意間用到也不會把它跟 多型 這個詞對應起來。在此拋磚引玉,大家討論...