封裝、繼承、多型,物件導向的三大特性,前兩項理解相對容易,但要理解多型,特別是深入的了解,對於初學者而言可能就會有一定困難了。我一直認為學習oo的最好方法就是結合實踐,封裝、繼承在實際工作中的應用隨處可見,但多型呢?也許未必,可能不經意間用到也不會把它跟「多型」這個詞對應起來。在此拋磚引玉,大家討論,個人能力有限,不足之處還請指正。
之前看到過類似的問題:如果面試時主考官要求你用一句話來描述多型,盡可能的精煉,你會怎麼回答?當然答案有很多,每個人的理解和表達不盡相同,但我比較趨向這樣描述:通過繼承實現的不同物件呼叫相同的方法,表現出不同的行為,稱之為多型。
例1:複製** **如下:
public class a程式設計客棧nimal
}public class cat : animal
}public class dog : animal
}class tester}}
輸出如下:
animal eat...
cat eat...
dog eat...
在上面的例子中,通過繼承,使得animal物件陣列中的不同的物件,在呼叫eat()方法時,表現出了不同的行為。
多型的實現看起來很簡單,要完全理解及靈活的運用c#的多型機制,也不是一件容易的事,有很多需要注意的地方。
1. new的用法
先看下面的例子。
例2:複製** **如下:
public class animal
}public class cat : animal
}class tester
}執行結果為:
animal eat...
animal eat...
cat eat...
可以看出,當派生類cat的eat()方法使用new修飾時,cat的物件轉換為animal物件後,呼叫的是animal類中的eat()方法。其實可以理解為,使用new關鍵字後,使得cat中的eat()方法和animal中的eat()方法成為毫不相關的兩個方法,只是它們的名字碰巧相同而已。所以, animal類中的eat()方法不管用還是不用virtual修飾,也不管訪問許可權如何,或者是沒有,都不會對cat的eat()方法產生什麼影響(只是因為使用了new關鍵字,如果cat類沒用從animal類繼承eat()方法,編譯器會輸出警告)。
我想這是設計者有意這麼設計的,因為有時候我們就是要達到這種效果。嚴格的說,不能說通過使用new來實現多型,只能說在某些特定的時候碰巧實現了多型的效果。
2.override實現多型
真正的多型使用override來實現的。回過去看前面的例1,在基類animal中將方法eat()用virtual標記為虛擬方法,再在派生類cat和dog中用override對eat()修飾,進行重寫,很簡單就實現了多型。需要注意的是,要對乙個類中乙個方法用override修飾,該類必須從父類中繼承了乙個對應的用virtual修飾的虛擬方法,否則編譯器將報錯。
好像講得差不多了,還有乙個問題,不知道你想沒有。就是多層繼承中又是怎樣實現多型的。比如類a是基類,有乙個虛擬方法method()(virtual修飾),類b繼承自類a,並對method()進行重寫(override修飾),現在類c又繼承自類b,是不是可以繼續對method()進行重寫,並實現多型呢?看下面的例子。
例3:複製** **如下:
public class animal
}public class dog : animal
}public class wolfdog : dog
}class tester
}}執行結果為:
animal eat...
dog eat...
wolfdog eat...
在上面的例子中類dog繼承自類animal,對方法eat()進行了重寫,類wolfdog又繼承自dog,再一次對eat()方法進行了重寫,並很好地實現了多型。不管繼承了多少層,都可以在子類中對父類中已經重寫的方法繼續進行重寫,即如果父類方法用override修飾,如果子類繼承了該方法,也可以用override修飾,多層繼承中的多型就是這樣實現的。要想終止這種重寫,只需重寫方法時用sealed關鍵字進行修飾即可。
3. abstract-override實現多型
先在我們在來討論一下用abstract修飾的抽象方法。抽象方法只是對方法進行了定義,而沒有實現,如果乙個類包含了抽象方法,那麼該類也必須用abstract宣告為抽象類,乙個抽象類是不能被例項化的。對於類中的抽象方法,可以再其派生類中用override進行重寫,如果不重寫,其派生類也要被宣告為抽象類。看下面的例子。
例4:複製** **如下:
public abstract class animal
public class cat : animal
}public class dog : animal
}public class wolfdog : dog
}class tester}}
執行結果為:
cat eat...
dog eat...
wolfdog eat...
從上面可以看出,通過使用abstract-override可以和virtual-override一樣地實現多型,包括多層繼承也是一樣的。不同之處在於,包含虛擬方法的類可以被例項化,而包含抽象方法的類不能被例項化。
以上就是我對c#中多型的一些淺薄的認識,如有錯誤的地方,歡迎批評指正!
本文標題: c#中的多型深入理解
本文位址: /ruanjian/csharp/104215.html
深入理解多型
能將每個函式都申明為虛函式,但是會影響效率,不建議這樣做,虛函式指標呼叫重寫函式是在程式執行時候進行的,因此需要一些定址操作才能真正呼叫函式,如果都設定成虛函式,效率會低很多 多型的實現效果 呼叫同樣的語句能表現不同的表現形式 多型實現的三個條件 有繼承,有虛函式重寫,有父類指標指向子類物件 多型的...
深入理解多型
1 黎克特制替換 概述 在子類物件中可以替換所有使用的父類物件 原則 父類物件是不能替換子類物件的 應用 使繼承復用成為可能,當子類可以替換父類時,軟體功能不受影響,父類才能真正被復用,而子類也能夠在父類的基礎上增加新的行為 關鍵字 is和a操作符 2 is和as操作符的使用 is操作符用於檢查物件...
深入理解多型
我們知道子類物件可以賦給父類物件,也可以說子類物件可以完全替換父類物件並出現在父類物件可以出現的任何地方,且程式的行為不會發生改變,但反過來父類物件是不能替換子類物件的!比如汽車類物件就不能替換卡車類物件 雖然卡車也是汽車 因為汽車包含的範圍比卡車要大,它也可以是私家車!這種特性就被稱為 黎克特制替...