这次主要分享的内容是关于继承的知识。
首先,我们先来看看继承;
既然有继承,就要有父类和子类,来看下面的一段代码:
class Person { private int nAge; protected string strName; double douHeight; public string strEateType; public void Hello() { Console.WriteLine("我可以说Hello!"); } public void Run() { Console.WriteLine("我可以跑!"); } } class Student : Person { }
然后我在Main()函数中实例化子类的对象,代码如下:
static void Main(string[] args) { Student stu1 = new Student(); }
那么在这个过程中内存中发生了些什么呢?
我们先来看misl的中间代码,看看那能发现些什么
由此我们可以发现子类继承了父类的所有成员包括Private和Protect,并为这些成员开辟了空间来存储。
我们再来实例化我们的子类,然后访问父类的字段和方法,会发现,如下的现象
所以虽然子类为父类的所有成员在堆中都开辟了空间,但是父类的私有成员(Private)子类访问不到,
而受保护的成员(protected)可以通过实例化对象访问的到。
所以在内存中的情况如下图:
看下面的代码,我们来探究一下在子类中this关键字和base关键字所访问的类的成员有哪些,代码如下:
class Student : Person { private string strClass; private string strAddress; public void Address(string cla, string adre) { //这里的this关键字调用了子类的成员和父类的非似有成员 this.strClass = "五"; this.strAddress = "北京"; this.strName = "子强"; //这里base关键字调用了是父类的非似有成员 base.strName = "强子"; Console.WriteLine("我是{0}年纪,来自{1}", cla, adre); } public void Sing() { this.strClass = ""; Console.WriteLine("我可以唱歌!"); } }
所以在子类中this关键字和base关键字的访问范围的示意图如下:
二,关于子类对象的构造函数和父类构造函数的执行顺序
当创建子类对象的时候
①先调用了子类的构造函数
②调用了父类的构造函数
③执行了父类的构造函数
④执行了子类的构造函数
微软
也就是说只要在子类显式的声明了无参的构造函数,在实例化子类的对象是,子类的无参构造函数都会去调用父类无参的构造函数。
那么,如果父类没有这个无参的构造函数则会报错。
父类的构造函数先于子类的构造函数执行的意义是什么呢?
当在父类的构造函数中和子类的构造函数中为父类的非私有成员变量赋不同默认值。当实例化子类,子类要调用构造函数初始化成员变量,如果先执行了子类的构造函数,再执行父类的构造函数,父类成员字段的值会覆盖子类成员字段的值。但是我们想得到的是子类的属性值。所以为了解决数据冲突,父类的构造函数要先于子类的构造函数执行。
三,子类是否可以有和父类的同名方法
可以,子类使用new关键字,隐藏从父类继承的同名方法,字段也是如此。