继承。构造函数调用序列
考虑我们有一个类 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
类构造函数; 然后调用链中的下一个构造函数,并且只有在调用它们之后才创建对象
基本关键字
- base 关键字用于从派生类中访问基类的成员:
- 在已被另一个方法重写的基类上调用方法。指定在创建派生类的实例时应调用哪个基类构造函数。