简体   繁体   English

C# 继承和默认构造函数

[英]C# inheritance and default constructors

Suppose there is a base class A and a class B derived from A .假设有一个基类A和一个从A派生的类B Then, we know that the constructor of class A is never inherited by class B .然后,我们知道类A的构造函数永远不会被类B继承。 However, when a new object of B is created, then - the default constructor of the class A is called prior to the default/custom constructor of class B is invoked.但是,当创建B的新对象时, - 在调用类B的默认/自定义构造函数之前调用类A的默认构造函数。 Maybe the purpose of this is that the fields of class A need to be initialized to default values.也许这样做的目的是需要将A类的字段初始化为默认值。

Now, suppose that class A has defined a custom constructor.现在,假设类A定义了一个自定义构造函数。 This means that the default constructor of class A is silently removed by the compiler.这意味着类A的默认构造函数会被编译器悄悄删除。 Now, on creating a new instance of class B , which constructor of class A is automatically called before invoking the class B 's constructor?现在,在创建类B的新实例时,在调用类B的构造函数之前会自动调用类A哪个构造函数? (How does the class A fields get initialized in such a case?) (在这种情况下如何初始化A类字段?)

Now, on creating a new instance of class B , which constructor of class A is automatically called before invoking the class B constructor?现在,在创建类B的新实例时,在调用类B构造函数之前会自动调用类A哪个构造函数?

The code will fail to compile, basically.基本上,代码将无法编译。 Each constructor has to chain to another constructor, either implicitly or explicitly.每个构造函数都必须隐式或显式地链接到另一个构造函数。 The constructor it chains to can be in the same class (with this ) or the base class (with base ).它链接到的构造函数可以在同一个类(与this )或基类(与base )。

A constructor like this:像这样的构造函数:

public B() {}

is implicitly:是隐含的:

public B() : base() {}

... and if you don't specify a constructor at all, it will be implicitly added in the same way - but it still has to have something to call. ...如果你根本不指定构造函数,它将以相同的方式隐式添加 - 但它仍然必须有一些东西可以调用。 So for example, your scenario:例如,您的场景:

public class A
{
    public A(int x) {}
}

public class B : A {}

leads to a compiler error of:导致编译器错误:

error CS7036: There is no argument given that corresponds to the required formal parameter 'x' of 'AA(int)'错误 CS7036:没有给出对应于'AA(int)'的所需形式参数'x'的参数

However, you can specify a different constructor call explicitly, eg但是,您可以显式指定不同的构造函数调用,例如

public B() : base(10) {} // Chain to base class constructor

or或者

public B() : this(10) {} // Chain to same class constructor, assuming one exists

Once you provide your own constructor to class A , no automatic invocations happens during the class B object creation.一旦您为class A提供了自己的构造函数,在class B对象创建期间就不会发生自动调用。

The first line in your class B constructor should be super(paramsToClassAConstructor) or it can be call to another constructor with in the class B using this() . class B构造函数中的第一行应该是super(paramsToClassAConstructor)或者它可以使用this()调用class B中的另一个构造函数。 It is the responsibility of the second constructor in class B to call the class A constructor in such case.在这种情况下, class B中的第二个构造函数负责调用class A构造函数。

When a constructor completes execution - the object is in a valid initial state.当构造函数完成执行时 - 对象处于有效的初始状态。 We are supposed to use objects which are valid.我们应该使用有效的对象。
When we provide a non-default constructor for class A - we are effectively saying - to construct class A object ie to be in the valid initial state - we need more information - which is provided by the parameters.当我们为 A 类提供非默认构造函数时——我们实际上是在说——构造 A 类对象,即处于有效的初始状态——我们需要更多信息——这是由参数提供的。
Given this, the compiler helps by not generating the default constructor.鉴于此,编译器通过生成默认构造函数来提供帮助。 The client code will fail to compile (as it should - how else will we make the object land in a valid state?) - and the client programmer would have to sit up and take notice.客户端代码将无法编译(因为它应该编译 - 我们还能如何使对象处于有效状态?) - 客户端程序员将不得不坐下来注意。
When you provide an explicit empty constructor - you are effectively telling the compiler - I know what I am doing - the default constructor would most probably initialize the fields to some sensible default values.当你提供一个显式的空构造函数时——你实际上是在告诉编译器——我知道我在做什么——默认构造函数很可能会将字段初始化为一些合理的默认值。
Or to promote reuse - the default constructor can call the non-default one with some default values.或者为了促进重用 - 默认构造函数可以使用一些默认值调用非默认构造函数。
A subclass knows about its super class - a sub-class constructor can invoke super class methods - (some commonly reused methods in sub-classes).子类知道它的超类——子类构造函数可以调用超类方法——(子类中一些常用的重用方法)。 Given the above - this requires that the super class part should be in a valid state - ie its constructor was executed prior to any of its method invocation .鉴于上述 - 这要求超类部分应该处于有效状态 - 即它的构造函数在其任何方法调用之前执行 This necessitates calling the super constructor before the sub-class constructor.这需要在子类构造函数之前调用超级构造函数。
Given this - you will easily be able to design your constructor to enforce the correct initial state behavior .鉴于此 - 您将能够轻松地设计构造函数以强制执行正确的初始状态行为

There is no special rule for defining base class parameter constructors.定义基类参数构造函数没有特殊规则。 Rules are same as other class constructors.规则与其他类构造函数相同。 You can define number of constructor as follows:您可以定义构造函数的数量如下:

class baseclass
    {
        public baseclass()
        {

        }
        public baseclass(string message)
        {

        }
    }

If base class has constructor then child class or derived class are required to call the constructor from its base class.如果基类有构造函数,那么子类或派生类需要从其基类调用构造函数。

class childclass : baseclass
    {
        public childclass()
        {
        }
        public childclass(string message)
            : base(message)
        {            
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM