公司項目是窗體應用程序,c#開發的。在看代碼了過程當中遇到了一個疑問,引起了以下思考。c#
疑問:要顯示的窗體是frmmain是繼承自customFrm這樣的基窗體的。當我實例化frmmain窗體的時候,(new frmmain()) as customFrm).show().我發現子窗體和父窗體的內容都能所有顯示出來。固然咱們須要的就是這樣。可是問題就來了。既然實例化子類,而後強制轉化爲父類。那麼父類就只能調用父類自己的成員,而沒法作到訪問子類成員了,那麼子類的成員是這麼在界面上顯示出來的? 寫了個簡單的demo,具體化這個問題ide
一個父類B以下:函數
public class B { public B() { } public string strB; public virtual void modifyUI_B() { Console.WriteLine("I am B"); } }
一個繼承B的子類Aspa
class A:B { public A() { } public string strA = ""; public void show_UI_A() { Console.WriteLine("I AM A_1"); } }
咱們在主函數main裏面寫這樣的代碼:調試
B b = (new A()) as B; Console.WriteLine("===================="); b.modifyUI_B(); // b.show_UI_A(); //沒法使用 Console.ReadKey();
問題具體化後,就是實例化A後,A自己看到是具有B和A的所有特性,強制轉化爲B類型。那麼B再也不擁有A的成員。就沒法調用A的方法Method_A_1().那麼我原先的問題,就出來了,子窗體被實例化強制轉化基窗體後,爲啥子窗體的內容仍是會呈現到界面上code
斷點調試後,發現緣由是這樣的。每當子類A實例化的時候,基類B的構造函數會先被執行一遍,而後纔是子類A的構造函數被執行一遍,因此後期,即便你強制轉化了成了基類,也是隻你無權訪問子類成員了。可是若是你的子類的顯示在構造函數裏被相應了,也一樣會被顯示出來。好比將面的demo該成這樣:對象
public class B { public B() { } public string strB; public virtual void modifyUI_B() { Console.WriteLine("I am B"); } } class A:B { public A() { show_U1_A(); } public string strA = ""; public void show_UI_A() { Console.WriteLine("I AM A"); } } static void Main(string[] args) { B b = (new A()) as B; Console.WriteLine("===================="); b.modifyUI_B(); Console.ReadKey(); }
若是改爲上面這種狀況,即便咱們轉化創基類,其實A界面的內容也會被顯示出來,由於它在構造函數裏面已經被調用了。繼承
而後若是咱們還要修飾界面風格,咱們能夠b.modifyUI_B();能夠了。這樣二者的的效果就會被疊加顯示。這就是爲何實際項目中,子窗體沒實例化後強制爲基窗體,界面子窗體的內容也能被顯示的緣由。就是在子類的構造函數上已經初始化了窗體要顯示的內容。最後強制的到的基類窗體對象只是沒法擁有子窗體的成員而已。接口
若是子類重寫了基類的方法,而後實例化了子類,再強制轉化爲基類,那麼調用方法響應的擁有時被重寫後的方法。開發
以下:
public class B { public B() { } public string strB; public virtual void modifyUI_B() { Console.WriteLine("I am B"); } } class A:B { public A() { show_U1_A(); } public string strA = ""; public void show_UI_A() { Console.WriteLine("I AM A"); } public override void modifyUI_B() { Console.WriteLine("此方法被子類已經重寫"); } } static void Main(string[] args) { B b = (new A()) as B; Console.WriteLine("===================="); b.modifyUI_B(); Console.ReadKey(); }
那麼咱們在子類強制轉化爲基類後調用modifyUI_B()的時候,其實仍然是調用的子類重寫的方法。
還有一點仍需注意的是,若是子類實例化後,轉化爲基類,而後再轉化爲子類,原來的特性就都回來了。
你們有沒有想過,若是基類實例化後,強制轉化爲子類又會是什麼狀況呢?
請看代碼:
public class B { public B() { } public string strB; public virtual void modifyUI_B() { Console.WriteLine("I am B"); } } class A:B { public A() { show_U1_A(); } public string strA = ""; public void show_UI_A() { Console.WriteLine("I AM A"); } public override void modifyUI_B() { Console.WriteLine("此方法被子類已經重寫"); } } static void Main(string[] args) { B b = (new A()) as B; Console.WriteLine("===================="); b.modifyUI_B(); Console.WriteLine("===================="); A a = new B() as A; a.modifyUI_B();//注意了,會報錯。由於a爲null a.show_UI_A();//注意了,會報錯。由於a爲null Console.ReadKey(); }
咱們能夠看到,咱們把一個基類實例化後,強制轉化爲子類的實例,無論你是調用了基類的方法仍是子類的方法,都會報錯。由於
基類強制轉化爲子類後,子類爲null。因此沒法調用成員。但願經過正反兩方面讓你們對繼承類之間的成員調用有更清晰的認識。
大二開始就知道繼承和接口什麼的,覺得本身看懂了,其實不少細節都不懂。。。