继承。构造函数调用序列

考虑我们有一个类 Animal,它有一个子类 Dog

class Animal
{
    public Animal()
    {
        Console.WriteLine("In Animal's constructor");
    }
}

class Dog : Animal
{
    public Dog()
    {
        Console.WriteLine("In Dog's constructor");
    }
}

默认情况下,每个类都隐式继承 Object 类。

这与上面的代码相同。

class Animal : Object
{
    public Animal()
    {
        Console.WriteLine("In Animal's constructor");
    }
}

在创建 Dog 类的实例时,如果没有对父类中的另一个构造函数进行显式调用,则将调用基类的默认构造函数(不带参数) 。在我们的例子中,首先将被称为 Object's 构造函数,然后是 Animal's,最后是 Dog's 构造函数。

public class Program
{
    public static void Main()
    {
        Dog dog = new Dog();
    }
}

输出将是

在 Animal 的构造函数中,
在 Dog 的构造函数中

查看演示

显式调用 parent 的构造函数

在上面的例子中,我们的 Dog 类构造函数调用了 Animal 类的默认构造函数。如果需要,可以指定应该调用哪个构造函数:可以调用父类中定义的任何构造函数。

考虑一下我们有这两个类。

class Animal
{
    protected string name;

    public Animal()
    {
        Console.WriteLine("Animal's default constructor");
    }    

    public Animal(string name)
    {
        this.name = name;
        Console.WriteLine("Animal's constructor with 1 parameter");
        Console.WriteLine(this.name);
    }
}

class Dog : Animal
{
    public Dog() : base()
    {
        Console.WriteLine("Dog's default constructor");
    }  

    public Dog(string name) : base(name)
    {
        Console.WriteLine("Dog's constructor with 1 parameter");
        Console.WriteLine(this.name);
    }
}

这是怎么回事?

我们在每个类中有 2 个构造函数。

base 是什么意思?

base 是对父类的引用。在我们的例子中,当我们像这样创建一个 Dog 类的实例时

Dog dog = new Dog();

运行时首先调用 Dog(),它是无参数构造函数。但它的身体不能立即起作用。在构造函数的括号之后,我们有一个这样的调用:base(),这意味着当我们调用默认的 Dog 构造函数时,它将依次调用父代的默认构造函数。在父项的构造函数运行之后,它将返回,然后最后运行 Dog() 构造函数体。

所以输出将是这样的:

Animal 的默认构造函数
Dog 的默认构造函数

查看演示

现在如果我们用参数调用 Dog's 构造函数怎么办?

Dog dog = new Dog("Rex");

你知道父类中非私有的成员是由子类继承的,这意味着 Dog 也将具有 name 字段。
在这种情况下,我们将参数传递给构造函数。它依次将参数传递给父类的构造函数,并使用参数初始化 name 字段。

输出将是

Animal's constructor with 1 parameter
Rex
Dog's constructor with 1 parameter
Rex

摘要:

每个对象创建都从基类开始。在继承中,层次结构中的类是链接的。由于所有类都来自 Object,因此在创建任何对象时要调用的第一个构造函数是 Object 类构造函数; 然后调用链中的下一个构造函数,并且只有在调用它们之后才创建对象

基本关键字

  1. base 关键字用于从派生类中访问基类的成员:
  2. 在已被另一个方法重写的基类上调用方法。指定在创建派生类的实例时应调用哪个基类构造函数。