Почему конструктор вызывается в обратном порядке? - PullRequest
5 голосов
/ 04 октября 2010

В наследстве, почему конструктор базового класса сначала получает вызов, а не производный ??

Ответы [ 4 ]

7 голосов
/ 04 октября 2010

Чтобы убедиться, что открытые или защищенные члены базового класса правильно инициализированы, прежде чем они будут использованы в производном классе.
Точнее говоря, сначала запускается конструктор производного класса с неявным вызовом базового класса.-класс-конструктор, вставленный компилятором в качестве первого оператора в теле конструктора производного класса (при условии использования конструкторов по умолчанию без аргументов).

3 голосов
/ 04 октября 2010

Подумайте, что могло бы произойти, если бы все было наоборот.Давайте представим пользовательский класс со значением _id._id из 0 - это специальные значения, которые представляют «гостевую» учетную запись (игнорируйте проблемы, связанные с «специальными значениями», во-первых, это не всегда плохая идея, а во-вторых, это только пример)._id также нельзя изменить после конструирования (что имеет смысл, если его можно было изменить, и он больше не является идентификатором).

public class User
{
  private readonly int _id;
  public User(int id)
  {
    _id = id;
  }
  public int ID
  {
    get { return _id; }
  }
  public bool IsGuest
  {
    get { return _id == 0; }
  }
}

Теперь рассмотрим класс Admin, который является подклассом из этого.Одним из правил класса Admin является то, что гость никогда не может быть администратором.Этот инвариант должен применяться во всех точках, которые может изменить статус гостя, который в данном случае находится только в конструкторе:

public class Admin : User
{
  public Admin(int id)
    :base(id)
  {
    if(IsGuest)
      throw new SecurityException("Guest users cannot be admins.");
  }
}

Если Admin был создан до User, тогда он всегда будет выдавать это исключение, так как тест всегда сравнивал бы 0 с 0. Если бы у нас было другое специальное значение для гостей, то это было бы еще хуже, и мы никогда не бросили бы исключение, даже когда это было бы необходимо, и учли бы проблему безопасности.

Помните также, что человеку, пишущему класс Admin, не нужно знать, как работает User, помимо того, что задокументировано относительно его открытого и защищенного интерфейса.Они могли бы уловить проблему, указанную выше, добавив свой собственный тест для определения того, равен ли id ноль или нет, но кроме того, что это является ненужным дублированием кода, нет причин, по которым они должны знать, как работает проверка IsGuest, и этобыть намного более сложным, чем это выше, и, возможно, возможно, запатентованным, запутанным и недокументированным.

В целом, вся концепция «построения администратора» не имеет смысла без концепции «создания пользователя» как чего-то, что произошло в первую очередь, мы не можем сделать более специализированный тип X без созданияX в качестве предпосылки.

3 голосов
/ 04 октября 2010

Производный класс создается путем расширения базового класса. Следует убедиться, что члены базового класса правильно инициализированы, прежде чем он может быть расширен в производном классе. Кроме того, члены, инициализированные в производном классе, не должны быть переопределены базовым классом.

2 голосов
/ 04 октября 2010

Что рождается первым, родитель или ребенок?

...