c#继承与构造函数的调用
c#继承与构造函数的调用
本片文章主要介绍在学习c#面向对象——继承,以及构造函数的继承调用时遇到的一些比较难理解的问题,希望对刚入门的朋友有一些帮助。
1、什么是继承,有什么作用?
概念:
继承就是在类之间建立一种相交关系,使得新定义的派生类(子类)的实例可以继承已有的基类(父类)的特征和能力,而且可以加入新的特性或者是修改已有的特性建立起类的新层次。
作用:
继承是面向对象的主要特征之一,它可以让你的代码重复使用,可以节省程序设计的时间,继承就是就是在类之间建立一种相交关系,使得新定义的派生类可以继承已有的基类的特征和能力,而且可以加入新的特性或者是修改已有的特性建立起类的新层次。
说明:
比如:你继承了你爸爸的一些特征,你爸爸是基类,你是派生类,你不仅有你爸爸的一些特征,同时你还有属于自己的一些习惯特征。也就是说你跟你爸爸共同拥有的一种特征,跟相同之处不同之处类似。
格式:
<访问修饰符符> class <基类>
{
...
}
class <派生类> : <基类>
{
...
}
2、类的继承规则
(1)继承是可传递的,如果C从B中派生,B又从A中派生,那么C不仅继承了B中声明的成员,同样也继承了A中的成员,Object类作为所有类的基类。
(2)派生类应当是对基类的扩展。派生类可以添加新的成员,但不能去除已经继承的成员的定义。
(3)被private修饰过的类成员无法被派生类继承。除此之外的其他成员(属性和方法),都可以被继承,都可以被派生类所访问。
(4)派生类如果定义了与继承而来的成员同名的新成员,就可以覆盖已经继承的同名成员,此时派生类不能访问被覆盖的成员。不过,使用new修饰符可以声明具有相同名称或签名的新成员。
(5)C#不支持多重继承,也就是说派生类只能从一个类中继承,但是可以通过接口实现多重继承。
(6)类可以定义虚方法、虚属性以及虚索引指示器,它的派生类能够重载这些成员,从而实现类可以展示出多态性。
3、派生类如何继承并调用基类的构造函数
方法:通过 :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 基类
{
public 基类() {}//无参构造函数
public 基类(类型 参数1){/*....*/}//有参构造函数
}
class 继承类:基类
{
public 派生类() {}//无参构造函数
public 继承类(类型 形数1,类型 形数2):base(实参1,实参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("我是犬科,派生类(子类)");
}
总结:
1、不管构造函数有没有参数,子类都会去调用这个父类的构造函数
2、当调用时,基类的构造函数总会比它的子类先调用或者输出
3、有参时,在这里base的作用是获取子类参数的实际值,以及给父类传值
4、无参时,base其实是被省略掉了
文章介绍结束,最主要的还是构造函数的继承调用问题,希望能给各位朋友一些帮助,如若本片文章有一些不足之处,或者说分析的不对的地方,还请各位朋友能够指出来,并在评论区评论,纠正我的错误,我希望大家的能够共同进步!
上一篇: jinjia2的使用
下一篇: 让优化方法在检讨中进步 学会反思