一、什么是继承,有什么作用?
概念:
继承就是在类之间建立一种相交关系,使得新定义的派生类(子类)的实例可以继承已有的基类(父类)的特征和能力,而且可以加入新的特性或者是修改已有的特性建立起类的新层次。
作用:
继承是面向对象的主要特征之一,它可以让你的代码重复使用,可以节省程序设计的时间,继承就是就是在类之间建立一种相交关系,使得新定义的派生类可以继承已有的基类的特征和能力,而且可以加入新的特性或者是修改已有的特性建立起类的新层次。
说明:
比如:你继承了你爸爸的一些特征,你爸爸是基类,你是派生类,你不仅有你爸爸的一些特征,同时你还有属于自己的一些习惯特征。也就是说你跟你爸爸共同拥有的一种特征,跟相同之处不同之处类似。
二、 继承中构造函数调用
如果一个类继承自其他类,那么子类和父类的构造函数是先调用父类中的构造函数,然后再调用子类中的构造函数。这样子类中就包含了父类的属性和方法,如下图
需要注意的是,如果一个类中没有定义构造函数,那么系统会自动为我们创建一个无参的构造函数,同理,如果该类是子类,且父类中也没有定义构造函数,那么在创建子类对象的时候,系统会默认的帮我们调用父类的无参构造函数。
在我们创建子类时会先执行父类的构造函数,再执行自己的构造函数子类实例化时,默认调用父类的无参构造函数,注意如果重写父类的构造函数,无参构造函数会被覆盖需要自己手动添加若不想使用父类的无参构造函数,可使用base关键字。
1)无参构造函数的继承调用问题
class Animal
{
public Animal()
{
Console.WriteLine("我是动物基类(父类)");
}
}
//基类的构造函数
class Dog : Animal
{
public Dog()
{
Console.WriteLine("我是小狗(子类)");
}
}
上边的代码等价于下边的代码
class Animal
{
public Animal()
{
Console.WriteLine("我是动物基类(父类)");
}
}
//基类的构造函数
class Dog : Animal
{
public Dog():base()//默认存在的base来调用父类的构造方法
{
Console.WriteLine("我是小狗(子类)");
}
}
说明:
1、基类的无参构造函数会被派生类无条件的直接继承和调用
2、在继承的时候是先调用父类的构造函数再调用子类的构造函数,意思就是说孩子有什么解决不了的问题找爸爸,爸爸解决不了的问题再找爸爸的爸爸,也就是孩子爷爷。就是这么个过程:先调用辈分大的构造函数,再调用辈分小的,一级一级往下调用,最终调用到本类中的构造函数。
3、其实在派生类无参构造函数中base是默认存在的,但是,因为是无参的,它的括号当中没有实际的参数,所以给省略,也就是上边的例子。
2)有参构造函数的继承调用问题
//基类
class Animal
{
public Animal(string name,string color,string eat)
{
Console.WriteLine("我是动物基类(父类)");
this.Name = name;
this.Color = color;
this.Eat = eat;
}
}
//派生类
class Dog : Animal
{
public Dog(string name, string color, string eat) : base(name, color, eat)
{
Console.WriteLine("我是犬科,派生类(子类)");
}
}
//外部调用
class Program
{
static void Main(string[] args)
{
Dog dog = new Dog("哈士奇","白黑相间","骨头");//实例化Dog对象,并通过构造函数传值
Console.WriteLine(hsq.Name + "颜色是" + hsq.Color + "喜欢吃" +hsq.Eat);
Console.ReadLine();
}
}
1、当父类的构造函数为有参的时候,那么它此时构造方法括号中的参数是形参,但是它必须要给定一个实参来接受,但是这个实参从何而来?
2、当父类构造函数为有参的时候,那么子类的构造函数也必须是有参数的,并且数据类型和个数要和父类的构造函数类型和个数相同,名称可以不同。
3、因为子类的形参它需要接收实参,那么我们就可以在实例化子类的时候给它实参,也就是下边的代码
Dog dog = new Dog("哈士奇","白黑相间","骨头");//实例化Dog对象,并通过构造函数给子类的构造函数传值
4、值传给子类的构造函数,但是此时父类没有呀,我想要继承父类,父类也应该有参数吧。 所以,这个时候就要通过:base来获取子类的传过来参数——实际的值(实参),并通过base把这个值传给父类的构造函数,此时父类构造函数的值就是子类获取到的值,因为是子类给父类传的实际参数。同时构造函数的作用就是初始化成员变量,那么子类传给父类的值就通过父类构造函数来初始化成员变量了。
public Dog(string name, string color, string eat) : base(name, color, eat)
//通过base来获取子类传过来的实际值,并给父类传过去,最后调用一下父类
{
Console.WriteLine("我是犬科,派生类(子类)");
}