標籤:style blog http color java 使用 os io
前言: 對菜鳥開發人員的忠告:花一萬個小時練習 Coding,不要浪費一萬小時無謂地 Debugging(也就說看代碼)
看上面的UML圖,我們建立一個抽象的Instrument類,類中有一個抽象方法paly,然後所有的子類都繼承這個類並實現paly方法。(若不懂繼承,請參照另一篇:OOP之繼承那點事)
我們來看一下類的實現:
public abstract class Instrument { public abstract void Play(); } public class Guitor : Instrument { public override void Play() { Console.WriteLine(string.Format("Play {0}", this.GetType().Name)); } } public class Paino : Instrument { public override void Play() { Console.WriteLine(string.Format("Play {0}", this.GetType().Name)); } } public class Violin : Instrument { public override void Play() { Console.WriteLine(string.Format("Play {0}", this.GetType().Name)); } }
View Code
在每個子類方法裡,我們直接出去字串。
class Program { static void Main(string[] args) { Guitor g = new Guitor(); g.Play(); Paino p = new Paino(); p.Play(); Violin v = new Violin(); v.Play(); Console.ReadLine(); } }
View Code
在Main方法裡,我們建立了三個對象,然後分別輸出。 這個說在我們還沒開始多態之前的寫法,好麻煩有木有(木有?蹲角落寫100個樂器的paly).那什麼是多態呢?
什麼是多態:一種形態的多種表現形式(好抽象...)
THINK IN JAVA上寫到:多態是消除類型之間的耦合關係(還是很抽象)
直接看例子:
class Program { static void Main(string[] args) { PlayInstrument(new Guitor()); PlayInstrument(new Paino()); PlayInstrument(new Violin()); Console.ReadLine(); } public static void PlayInstrument(Instrument instrument) { instrument.Play(); } }
View Code
這樣的輸出是和上面的例子是一樣的,我們改變了什麼,我們提供了一個方法,把3個子類的引用放了進去,呀,為什麼PlayInstrument的形參是Instrument的對象,這就是多態的關鍵之處,
我總結了一句話:子類的引用(new Guitor())指向父類的對象(Instrument instrument) ;
static void Main(string[] args) { Instrument instrument = new Guitor(); instrument = new Paino(); instrument = new Violin(); Console.ReadLine(); }
View Code
這個好神奇有木有,我初學時間也覺得,這個好神奇,這個這麼玩的,讓我來帶領大家進入神秘的多態空間。
向上轉型
static void Main(string[] args) { Guitor gutior = new Guitor(); Instrument instrument = gutior; Console.ReadLine(); }
View Code
向上轉型,就說把子類的類型轉成父類的,這樣是安全的,看上面的例子,如果在VS IDE工具中查看,是沒有編譯報錯的,這時為什麼呢?我們來看張圖。
這個圓我們把他當作堆(heap)來看,(這沒有畫棧,因為指向討論向上轉型的安全).我們來看一下Guitor裡麵包含了Instrument的所有的東西(除了構造,如果說你點不出來私人化的東西,你可以嘗試用反射,它的確存在) ,這樣我們把大塊變成小塊是不是很安全呢,因為我大塊擁有小塊裡面所有的東西,所以說向上轉型是安全的。
註:相反來說,向下轉型是危險的,因為小塊變成大塊,你不可以控制裡面的東西。(協變和逆變概念也差不多,我比較喜歡叫成和諧的變->安全,逆天的變->危險)
這樣的話,我們把大塊轉換成小塊(Instrument instrument=new Guitor()),我們只能調用到小塊的東西了(所以我們在設計的時候,一般會用介面去限定)
介面其實是應該單獨拉出來談的,但是由於介面基本概念不多,只是在我們OO設計中,介面用處很大,這裡屬於設計範圍,在多態中,用介面做父類和用類寫法一樣的,可以去試試。
總結一下:
1.向上轉型以後,雖然引用還是原本的子類,但是只能用父類的方法了(想想大塊變小塊)
2.父類方法被子類重寫了(virtual,override)以後,向上轉型以後,調用相同的方法還是大塊的(因為小塊的被重寫了,這樣說感覺很牽強,因為如果我們在子類中用base關鍵字還是能調用父類的同名方法,至於這塊的記憶體的調用,我一直沒找到相關資料,如果有人知道,請分享一下,萬分感謝)。
3.介面和抽象類別(類)在使用多態的上面是同一個形式
感覺這邊寫的不好...望大家補充和指出不足,謝謝了。