Наследование конструкторов

Наследование конструкторов

Правила наследования конструкторов - достаточно сложные. В разных языках программирования приняты разные решения на этот счет. В частности, в Delphi Object Pascal все конструкторы наследуются. В .NET, напротив, конструкторы не наследуются. Причина такого решения - каждый класс сам должен отвечать за инициализацию своих экземпляров. Единственное исключение в .NET - если класс вовсе не определяет конструкторов, то автоматически генерируется конструктор без параметров, называемый конструктором по умолчанию.

В PascalABC.NET принято промежуточное решение. Если класс не определяет конструкторов, то все конструкторы предка автоматически генерируются в потомке, вызывая соответствующие конструкторы предка (можно также говорить, что они наследуются). Если в классе определяются конструкторы, то конструкторы предка не генерируются. Конструктор по умолчанию, если он явно не определен, генерируется автоматически в любом случае и является protected.

Кроме того, в .NET обязательно в конструкторе потомка первым оператором должен быть вызван конструктор предка; в Object Pascal это необязательно. Если в PascalABC.NET конструктор предка вызывается из конструктора потомка, то этот вызов должен быть первым оператором. Если конструктор предка явно не вызывается из конструктора потомка, то неявно первым оператором в конструкторе потомка вызывается конструктор предка по умолчанию (т.е. без параметров). Если такого конструктора у предка нет (это может быть класс, откомпилированный другим .NET-компилятором или входящий в стандартную библиотеку классов - все классы, откомпилированные PascalABC.NET, имеют конструктор по умолчанию), то возникает ошибка компиляции.

Например:

type
  A = class
    i: integer;
    // конструктор по умолчанию не определен явно, поэтому генерируется автоматически
    constructor Create(i: integer);
    begin
      Self.i := i;
    end;
  end;
  B = class(A)
    j: integer;
    constructor Create;
    begin
      // конструктор по умолчанию базового класса вызывается автоматически
      // конструктор по умолчанию определен явно, поэтому не генерируется автоматически
      j := 1;
    end;
    constructor Create(i,j: integer);
    begin
      inherited
Create(i);
      Self.j := j;
    end;
  end;
  C = class(B)
  // класс не определяет конструкторов, поэтому
  // конструктор по умолчанию и constructor Create(i,j: integer)   
  // генерируются автоматически, вызывая в своем теле соответствующие конструкторы предка
  end;