理解C#中的继承
继承
1、创建子类对象的时候,在子类对象中会为子类对象的字段开辟空间,也会为父类对象的所有字段开辟空间。只不过父类私有的成员访问不到而已。
2、base关键字可以调用父类的非私有成员。
3、子类的访问级别不能比父类的高。
4、创建子类对象的时候,1)调用子类的构造函数。2)调用父类的构造函数。3)执行父类的构造函数。4)执行子类的构造函数。
5、子类的构造函数,默认加了一个base()通过这个调用父类的无参数的构造函数。如果父类没有无参数的构造函数,将会报错,因为子类的构造函数默认会调用父类的无参数的构造函数。使用base关键字可以显示的指定子类构造函数调用父类有参的构造函数。
1 class Teacher 2 3 { 4 5 public int age{get;set;} 6 7 public string name{get;set;} 8 9 public bool gender{get;set;} 10 11 public Teacher(int age,string name,bool gender) 12 13 { 14 15 this.age=age; 16 17 this.name=name; 18 19 this.gender=gender; 20 21 } 22 23 } 24 25 26 Class Student:Teacher 27 28 { 29 30 public Student(int age,string name,bool gender,string stuNo):base(age,string,) 31 32 { 33 34 this.StuNo=stuNo; 35 36 } 37 38 }
6、类只能有一个父类。
7、父类和子类存在同名成员的时候,如果创建一个子类对象,调用这个子类对象的同名方法,会调用子类的。new关键字的第二个作用,隐藏父类的同名成员。
调用对象的成员,如果该对象中有则结果为其值,如果没有,则继续往上找它的父类,结果为其父类的值。
8、里氏替换原则(LSP):子类可以替换父类的位置,并且程序的功能不受影响。即父类变量指向了一个子类对象,父类有的功能子类都有,所以不影响程序的功能。
1 Person p=new Person(); 2 3 p.SayHi();//调用父类的 4 5 Student s=new Student(); 6 7 s.SayHi();//调用子类的 8 9 Person p1=new Student(); 10 11 p1.SayHi();//调用父类的,子类独有的调不到。类型指针指向谁,是根据指向对象的变量的类型决定的,如果调用的方法没有,就找person父类。 12 13 p1.Age=19; 14 15 p1.Name="小花";
9、子类变量不能指向一个父类对象。反之可以。
1 Person p=new Person(); 2 3 Student s=new Student(); 4 5 p=s;//可以 6 7 Person p1=new Student(); 8 9 Student s1=(Student)p1;//可以。p指向的是一个子类对象,可以将其强制转成子类对象。必须有继承关系,才能使用强制转换。 10 11 Student s0=(Student)p;//会报异常,1个父类变量p指向的就是一个父类对象,将p转成子类对象时报异常。 12 13 Program pr=new Program(); 14 15 s1=(Student)p1;//不行。没有继承关系。 16 17 //is 判断变量是否为指定数据类型。 18 19 bool b=p is Person; 20 21 //as转换,如果转换成功引用指s4,如果失败,不报异常,返回null 22 23 Student s3=(Student)p;//有可能报异常 24 25 Student s4=p as Student;
10、父类变量指向子类对象,如果子类重写了父类的虚方法,那么,通过父类变量来调用方法的时候,会调用子类的。
1 Person p=new Teacher(); 2 3 p.SayHi();//调用子类,如果子类没有override则继续找子类的父类看是否覆写了。