公司项目是窗体应用程序,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。因此没法调用成员。但愿经过正反两方面让你们对继承类之间的成员调用有更清晰的认识。
大二开始就知道继承和接口什么的,觉得本身看懂了,其实不少细节都不懂。。。