Типы классов и вызовы конструктора - PullRequest
2 голосов
/ 06 августа 2009

Если я пишу

type
  MyClass = class of TMyClass;
...
Obj := MyClass.Create;

, вызывается правильный конструктор (в TMyClass).

Если я пишу

var
  ClassVar : TClass;
...
ClassVar := TMyClass;
Obj := ClassVar.Create;

, только конструктор TObjectназывается.

Почему?В чем разница между двумя версиями?Могу ли я вызвать вызов конструктора TMyClass во втором сценарии?

Ответы [ 4 ]

11 голосов
/ 06 августа 2009

TClass объявлен как "Class of TObject" в system.pas. Какой конструктор вызывается, определяется во время компиляции, и все, что знает компилятор, это какой базовый класс вы используете. Он не знает, каким будет значение переменной при запуске, поэтому он должен по умолчанию использовать базовый класс. Если вы используете TClass, то ваш базовый класс - TObject.

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

type
  TMyBaseObject = class(TObject)
  public
    constructor Create; virtual;
  end;

  TMyClass = class of TMyBaseObject;

Используйте TMyClass вместо TClass в качестве переменной класса, и теперь компилятор сгенерирует вызов TMyBaseObject.Create, который является виртуальным. Убедитесь, что все ваши производные классы переопределяют базовый конструктор, и в итоге вы вызовете правильный конструктор.

4 голосов
/ 06 августа 2009

TObject.Create не является виртуальным, вам нужно объявить ClassVar как класс-класс с виртуальным конструктором.

2 голосов
/ 06 августа 2009

Я бы посоветовал вам переопределить метод AfterConstruction, представленный объектом TObject, чтобы сделать полиморфизм подобным этой работе.

Каждое определение класса может вводить новый конструктор со своим собственным набором параметров. Переменная класса знает конструктор только в том случае, если для базового класса она является переменной. Это все возможно, потому что конструктор не является ни виртуальным, ни переопределенным. Вы можете пометить конструктор виртуальный в вашем базовом классе и пометить все нисходящие классы переопределить, что блокирует список параметров. (Я думаю, что если вы забудете «переопределить», компилятор предупредит, что ваш новый конструктор скрывает виртуальный.)

0 голосов
/ 07 августа 2009

Или удалите его из TComponent, у которого уже есть виртуальный конструктор.

...