构造函数以及继承中的构造函数
何为构造函数?
构造函数是实例化对象时(即创建类的新对象时)所调用的函数,主要用来初始化成员变量,每个类都会有默认的一个无参构造函数,构造函数不需要写返回值
class Student{
}
Student stu=new Student();
这段代码是不是很熟悉?这其实就是对Student类中默认的无参构造函数的调用,即使Student类中并没有写出这个方法,但是他是默认自带的,他为新的stu对象分配了内存空间
当然,虽然自带无参构造函数,我们同样可以吧他写出来,如下
语法
访问修饰符类名(){
}
注意:构造函数的名称与类的名称必须完全相同,它没有任何返回类型。
class Person{
string name;
int age;
string phone;
public Person(){
name = "红笺";
age = 17;
}
}
当我们现在再调用构造函数时,会执行函数里面的代码,为name,age赋值
注意:类中是允许自己申明无参构造函数的,而结构体中不允许
构造函数可以被重载,也就是说可以写有参构造函数
public Person(int age){
this.age = age; //this.age表示当前调用该函数的对象自己的age,而age表示调用有参构造函数是传进来的参数age
}
public Person(string name,int age){
this.age = age;
this.name = name;
}
有参构造函数怎么使用呢?
实例化对象时,对比有参构造函数写出相应的语句即可,如我想实例化一个有年龄的对象,可以
Person p1=new Person(17);
// public Person(int age)
如我想实例化一个有年龄有姓名的对象,可以
Person p2=new Person("大学生",18);
// public Person(string name,int age)
注意!当重写了有参构造函数,并且没有重写无参构造函数时,无参构造函数会默认被顶掉(会失去默认的无参构造函数),也就是说写
Person p=new Person();
时,会报错。
!!!!!!一定要注意
如果想使用有参构造函数的同时使用无参构造函数,则需要重写无参构造函数,即写出
public Person(){
}
这个无参构造函数即可
重载对我们的好处很多,可以在实例化对象的的时候对对象进行成员变量的初始化等等,很方便
理论上重载可以写无数个,根据需求而定
构造函数的特殊写法:
可以通过this重用构造函数代码
访问修饰符 构造函数名(参数列表) : this(参数1,参数2,参数3.....){
}
重点咯,我会通过许多例子来帮助你理解this的作用
理论知识是,当你如上写代码的时候,会默认优先调用this(该函数对象自己)的方法,再调用现在写的方法
比如
public Person(string name) : this("xiahua",19)
{
this.name=name;
}
如上例子
我在使用
Person p3=new Person("xiaoming");
时,会先调用this后面这个构造函数,括号内是一个字符串,一个int值类型符合==Person(string name,int age){}==这个构造函数,所以会先执行这个构造函数,再执行Person(String name)这个函数
再举个例子
public Person(string name,string phone) : this(19)
{
this.name = name;
this.phone = phone;
}
我在使用
Person p3 = new Person("xiaoming","11915768459");
函数时,会先调用this后面这个构造函数,括号内是一个int值类型符合==Person(intage){}==这个构造函数,所以会先执行这个构造函数,为age赋值,再执行Person(Stringname,stringphone)这个函数,为name,phone赋值
也就是说,只要构造函数后面带了**=:this()这个标识,调用==:之前的构造函数==时会先调用**:后面的函数,再调用前面的函数
this()可以是无参的,this()括号中的参数,可以是从前面传进来的,也可以是自己写的默认值,只要类型一样,传什么都行
}
继承中的构造函数
特点
当申明一个子类对象时,先执行父类()的构造函数,在执行子类的构造函数
注意:父类的无参构造很重要,子类可以通过base关键字代表父类,使用父类的构造函数
继承中构造函数的执行顺序
父类的父类的构造->父类构造->子类构造,继承多少个调用多少个
class GrandFather{
public GrandFather(){
Console.WriteLine("爷爷");
}
}
classFather : GrandFather{
publicFather(){
Console.WriteLine("爸爸");
}
}
classSon : Father{
publicSon()
{
Console.WriteLine("儿子");
}
输出结果会是爷爷,爸爸,儿子
父类的无参构造很重要
class Big{
public Big(int a){
Console.WriteLine("父类的有参构造");
}
public Big(){
}
//重写出无参构造函数就不会报错了
}
classSmall : Big{
}
重写了父类的有参构造函数,默认无参构造函数已经没有了,此时子类便会报错,当你实例化一个子类的时候,会自动先调用父类的构造函数,而父类的默认无参构造函数没有了自然会报错,所以如果重写了父类的构造函数,记得吧无参构造函数一并重写了
通过base调用指定父类构造
与前文this相似
如果你实在不想写父类的无参构造,或者就是想在实例化子类的时候调用父类的有参构造,可以使用base指定父类的有参构造函数
class FFather{
publicFFather(inta){
Console.WriteLine("父类的有参构造");
}
}
class SSon : FFather{
public SSon(int i) : base(i){
}
}
逻辑是这样的只要你子类实例化的时候,必定会调用父类的构造函数,如果你实例化没有传参就要调用父类的无参构造,如果你的无参构造被顶掉了,肯定会报错,
如果你实例化传参了,就要调用父类的有参构造,传入的参数类型跟父类的有参构造的参数要一样