我們再寫第四個版本的run方法,我們稱之為run3(),這次父類中run3()的修飾符與第三個版本相比沒有變化(依然是virtual,虛方法),而子類son中的run3()方法與第三個版本相比多了乙個override修飾符(這次我們熟悉的那個棕色的波浪線警告沒有了)。**如下:
///
/// 父類
/// 日期:2008-09-01
///
public
class father }
///
/// 子類
/// 日期:2008-09-01
///
public
class son:father }
class program }
程式的執行結果如下:
father.run3
son.run3
這次我們發現程式的執行結果與前面三次不一樣了,這次儘管我們宣告的物件型別都是father類(father數組裝的自然都是father型別的引用),但是因為例項化陣列中第二個元素的時候呼叫了son類的建構函式,也就是例項化了乙個father類的子類(我們知道子類可以當作父類來看待,他們之間是is a的關係,反之則不行),也就是說fatherlist陣列中的第二個元素的引用型別是father型別,但它的例項型別確實son型別。而在執行的時候,並不是根據我們的引用型別(引用型別是father型別的)去呼叫該引用型別的方法,而是呼叫該引用型別所指向的例項的方法。
為什麼會發生這些現象呢?這裡要提到兩個概念:早繫結(early binding)和晚繫結(late binding)
。這個術語出現在存在繼承關係的基類和派生類中,它們同時定義了乙個同名同參的方法。
早繫結:在編譯的時候就已經確定了將來程式執行基類或是派生類的哪個方法。在編譯**的時候根據引用型別就決定了執行該引用型別中定義的方法,即基類的方法。這種方法執行效率高。
晚繫結:只有在執行的時候才能決定執行基類或者派生類中的哪個方法。執行的時候將根據該實際型別而不是引用型別來呼叫相關方法,即取決於我們new了什麼樣物件。也就是即使我們new乙個father類的子類son的例項,而不管我們是用father類的引用指向這個son的例項,方法呼叫的時候依然是呼叫son的方法,而不是father類的同名方法。
但是如果在基類中顯示宣告方法為虛方法,那麼clr在執行的時候會進行型別檢查,如果發現引用型別和實際的物件型別不一致,就會檢查派生類中是否覆蓋(override)了基類中的方法,如果是,則會執行派生類中的方法,而不是引用型別中的方法。
抽象方法與虛方法
在物件導向程式設計語言中抽象方法指一些只有方法宣告,沒有具體方法體的方法。抽象方法一般存在於抽象類或介面中。在c 中,抽象方法具有以下特性 抽象方法是隱式的virtual方法 只允許在抽象類中使用抽象方法宣告 因為抽象方法不提供實現,所以沒有方法體 方法宣告只是以乙個分號結束,並且在簽名後沒有大括號...
new方法和虛方法
new方法 在繼承父類時相同的方法可能有不同的表現形式,比如說talk 父類中 class mammal 子類中 class horse mammal 使用new關鍵字重寫父類中talk 方法,將父類中的talk 隱藏 所以在例項化時 horse bighorse new horse bighors...
虛方法與非虛方法
非虛方法 如果方法在編譯期就確定了具體的呼叫版本,這個版本在執行時是不可變的,這樣的方法稱為非虛方法 靜態方法 私有方法 final方法 例項構造器 父類方法都是非虛方法 虛方法 不是非虛方法的方法,都是虛方法 呼叫指令 虛擬機器中提供了以下幾條方法呼叫指令 普通呼叫指令 1 invokestati...