c# 的继承,继承类实例化的时候,会先调用基类的构造函数,然后再调用自己的构造函数,base 的用法,有override和没有override的区别

首先举个例子:

运行结果是

image

namespace 继承
{
   
class Program
   
{
       
static void Main(string[] args)
        {
           

           
China joey = new China();           //第一个中国人,首先会调用People的无参构造函数,然后再调用China类自己的无参构造函数


           
China lidashu = new China(2);        //如果在 China 类的带1个参数的构造函数 后面 没写base,则先调用People的无参构造函数,然后是China的有参 。
            //如果有写 base ,则先调用 People的带参数的构造函数,再是China的有参
                                                   
                                                                   
           
China xiaoming = new China("小明", 3); 
        }
    }

   
class People
   
{
       
public People()  //父类的无参构造函数
       
{
           
Console.WriteLine("默认的无参构造函数");
        }
       
public People(int i)
        {
           
Console.WriteLine("People带1个参数的构造函数");
        }
      
    }

   
class China : People   
   
{
       
public China()//等价于  public China():base()   表示这个China的无参构造函数 会隐式调用 People()这个无参数的构造函数
       
{
           
Console.WriteLine("创建了一个中国人");
        }
       
public China(int num)
       
//: base(num)        //如果这里有写 base(num)  则调用People类的 People(int i) 这个构造函数,如果没有写base,那么还是 隐式调用People()这个无参数的构造函数
       
{
           
Console.WriteLine(num + "个中国人");
        }



       
public China(string name, int num): base(num)   //虽然China子类的构造参数的个数同People父类不一样,但是没关系,一样可以传值到父类进行调用父类的构造参数
                                                         //至于是调用父类的哪个构造参数,就要看这里的 base 后面有几个参数,并且要看传入的是什么值类型
       
{
           
Console.WriteLine(num + "个中国人,名字是" + name);
        }
    }
}

 

结论:

1:继承的写法     用冒号 :  来表示继承    (接口也是用 冒号 :  来表示的,这个要注意)。子类是调用父类的构造函数,而不是继承了父类的构造函数.

 

2:  如果子类,在写构造参数的时候,如果没有写 :base()   则是隐式的调用父类的 无参数的构造函数(如果父类没有无参数的构造函数,则什么都不干,如果父类,只有带参数的构造函数,而没有无参数的构造函数,则子类在写构造函数的时候,必须写 base(num),这是因为,父类已经没有无参的构造函数了,但是子类总是会调用A的构造参数的,这个时候我们的父类没有无参构造函数,所以你子类必须显式的来用base来告诉是调用父类的哪个有参。如果父类根本就没有构造函数,则子类就无所谓了,因为此时相当于父类是有一个空的无参构造函数)

                                                  如果有写 base  ,则根据 base 后面的挂号里面的参数来调用父类的构造参数,例如  base()  这个是调用父类默认的无参构造,如果是 base(j) ,则是父类的1个参数的构造参数

3:特殊的情况,子类的构造参数,有多个参数,例如   public China(string name, int num): base(num)   ,这个表示 子类有2个参数,调用父类的一个带参的构造函数,也就是说,调用父类多少个构造参数,是由后面的base挂号里面的参数来决定的,如果是base() 或者没有写,就是调用父类默认的无参构造函数。如果是多个,则匹配父类同样个数的有参构造函数

 

 

如果子类里面,有自带的字段呢?


namespace
继承
{
   
class Program
   
{
       
static void Main(string[] args)
        {
           
B b = new B();
           
//这个运行的结果是 打印下面的2行
            //x=1,y=0
            //x=1,y=-1
       
}
    }
   
class A
   
{
       
public A()
        {
            PrintFields(); 
//步骤2:在调用A的构造的时候,因为这是个虚方法,而且子类又用 override 进行了重写,所以会去调用子类的 override 方法
       
}
       
public virtual void PrintFields() { }
    }
   
class B : A
   
{
       
int x = 1;
       
int y;            //步骤1:在b实例化的时候,会先运行 x=1,y=0的赋值,然后开始执行B的构造的时候,先去调用A的默认构造
       
public B()     //步骤4: 父类的构造函数完成之后,开始子类的构造方法,执行这个输出语句
       
{
            y = -1;
           
Console.WriteLine("x={0},y={1}", x, y);
        }
       
public override void PrintFields()  //步骤3 :  运行这个方法
       
{
           
Console.WriteLine("x={0},y={1}", x, y);
        }

    }
}

 

4:如果子类有字段,那么会先给字段赋值,再执行构造函数

5:如果父类有 virtual 函数,但是子类 没有写  override 来进行重写的话,那么子类这个函数是不执行的。(父类的会执行,但是子类不执行)

 

例如

class Program
    {
        static void Main(string[] args)
        {
            B b = new B();
            //这个运行的结果是 打印下面的1行 
            //x=1,y=-1
        }
    }
    class A
    {
        public A()
        {
            PrintFields();  //2:在调用A的构造的时候,虽然这是个虚方法,但是子类没有写 override 进行重写,所以不执行子类
        }
        public virtual void PrintFields() { }   //3:因为子类没有 override ,所以不执行子类的重写,而是会运行这里的空的函数
    }
    class B : A
    {
        int x = 1;
        int y;         //1:在b实例化的时候,会先运行 x=1,y=0的赋值,然后开始执行B的构造的时候,先去调用A的默认构造
        public B()     //4: 父类的构造函数完成之后,开始子类的构造方法,执行这个输出语句
        {
            y = -1;
            Console.WriteLine("x={0},y={1}", x, y);
        }
        public  void PrintFields()  //因为这里没有写 override 所以这个函数从头到尾压根都没有执行··
        {
            Console.WriteLine("x={0},y={1}", x, y);
        }

    }

 

关于base的用法

–1.调用父类中非私有的成员(调用成员,父类),  base点不出子类独有成员。

–2.调用父类中的构造函数(调用构造函数,父类)

•当调用从父类中继承过来的成员的时候,如果子类没有重写则this.成员;那么this.成员与base.成员,没有区别,都是指的父类的成员。

如果子类重写了父类成员,则this.成员;调用的是子类重写以后的成员。   而base.成员;调用的依然是父类的成员。

•子类构造函数默认调用父类的无参构造函数;

•如果父类没有无参构造函数,则必须指明调用父类哪个构造函数

posted @ 2012-06-04 16:07  asp_net老友记  阅读(1036)  评论(0编辑  收藏  举报