Подтвердить что ты не робот

С# наследование и конструкторы по умолчанию

Предположим, что существует базовый класс A и класс B, полученный из A. Затем мы знаем, что конструктор класса A никогда не наследуется классом B. Однако, когда создается новый объект B, тогда - конструктор по умолчанию класса A вызывается до того, как по умолчанию/пользовательский конструктор класса B вызывается. Возможно, целью этого является то, что поля класса A должны быть инициализированы значениями по умолчанию.

Теперь предположим, что класс A определил пользовательский конструктор. Это означает, что конструктор по умолчанию класса A молча удаляется компилятором. Теперь, при создании нового экземпляра класса B, какой конструктор класса A автоматически вызывается перед вызовом конструктора class B? (Как поля класса A получают инициализацию в таком случае?)

4b9b3361

Ответ 1

Теперь, при создании нового экземпляра класса B, какой конструктор класса A автоматически вызывается перед вызовом конструктора класса B?

В общем случае код не будет скомпилирован. Каждый конструктор должен привязываться к другому конструктору, как неявно, так и явно. Конструктор, к которому он привязан, может находиться в одном классе (с this) или базовым классом (с base).

Конструктор, подобный этому:

public B() {}

неявно:

public B() : base() {}

... и если вы вообще не укажете конструктор, он будет неявно добавлен таким же образом, но ему все равно придется что-то вызывать. Например, ваш сценарий:

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

public class B : A {}

приводит к ошибке компилятора:

ошибка CS7036: нет аргументов, которые соответствуют требуемому формальному параметру 'x' of 'A.A(int)'

Однако вы можете явно указать другой вызов конструктора, например.

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

или

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

Ответ 2

Как только вы предоставите свой собственный конструктор class A, при создании объекта class B автоматические вызовы не будут выполняться.

Первая строка в вашем конструкторе class B должна быть super(paramsToClassAConstructor) или может быть вызвана другим конструктором с class B с помощью this(). В этом случае второй конструктор в class B отвечает за вызов конструктора class A.

Ответ 3

Когда конструктор завершает выполнение - объект в допустимом начальном состоянии. Мы должны использовать объекты, которые являются действительными.
  Когда мы предоставляем конструктор не по умолчанию для класса А, мы эффективно говорим - чтобы построить объект класса А, т.е. Находиться в правильном начальном состоянии - нам нужна дополнительная информация, предоставляемая параметрами.
  Учитывая это, компилятор помогает не генерировать конструктор по умолчанию. Клиентский код не сможет скомпилировать (как и должно - как еще мы сделаем объект земли в правильном состоянии?) - и клиентскому программисту придется сесть и принять к сведению.
  Когда вы предоставляете явный пустой конструктор - вы эффективно говорите компилятору - я знаю, что я делаю - конструктор по умолчанию, скорее всего, инициализирует поля некоторыми разумными значениями по умолчанию.
  Или для содействия повторному использованию - конструктор по умолчанию может вызывать нестандартный с некоторыми значениями по умолчанию.
  Подкласс знает о его суперклассе - конструктор подкласса может вызывать методы суперкласса - (некоторые часто используемые методы в подклассах). Учитывая вышеизложенное - это требует, чтобы часть суперкласса должна находиться в состоянии valid, т.е. Его конструктор был выполнен до любого его вызова метода. Это требует вызова супер-конструктора перед конструктором подкласса.
  Учитывая это - вы легко сможете сконструировать свой конструктор для обеспечения правильного поведения начального состояния.