Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Конструктор потомка


Автор: Snowy 23.1.2006, 14:58
Вот такая головоломка меня преследует:
Код

  TCustomClass = class // предок
  private
    MyName: string; // переменная, задается в конструкторе
  public
    constructor Create; // соответственно конструктор
    function SayYourName:string; virtual; // метод, есть в родителе и потомке
  end;

  TMyClass = class(TCustomClass) // потомок. В примере только один
    constructor Create; // конструктор потомка! Вот он мне и нужен!
    function SayYourName: string; override; // метод
  end;

  TClasses = class of TCustomClass; // определяет тип класса, создаваемого объекта

var Form1: TForm1;

implementation
{$R *.dfm}

function CreateNewClass(ClassId: TClasses):TCustomClass; // Функция, которая создает новый объект
begin  // неизвестного пока нам класса. Конкретный класс будет определен позже
  result := ClassId.Create; // вот, мы вызываем конструктор
end;

constructor TCustomClass.Create; // конструктор родителя
begin
  inherited;
  MyName := 'Кустомчик';
end;

constructor TMyClass.Create; // конструктор потомка. Не вызывается никогда!!! А надо!
begin
  inherited;
  MyName := 'Потомок Кустомчика';
end;

function TCustomClass.SayYourName; // реализация функции родителя
begin
  result := MyName;
end;

function TMyClass.SayYourName; // реализация функции потомка
begin
  result := 'Меня зовут ' + MyName;
end;

procedure TForm1.Button1Click(Sender: TObject); // действие
begin
  with CreateNewClass(TMyClass) do // вот мы вызываем конструктор. Говорит, создай нам потомка.
  begin
    ShowMessage(SayYourName + #13#10 + ClassName); // Проверяем, что же у нас получилось...
    Free;
  end;
end;

Итого, в результате примера данного кода получаем следующее.
Смотрим последнюю часть - действие.
1. Вызывается функция, которая создает нам объект. Сообщаем ей, что хотим потомка.
2. Функция вызывает конструктор. Но! Вызывается конструктор не потомка, а предка!!!!! smile
Конструктор потомка вообще не вызывается!!!
Трейсил все по F7. В конструктор потомка не идет!
3. Отработал конструктор предка. Проверяем, что же мы создали.
Как видим, функция в потомке отличается от функции в предке.
Вызываем ее. Вызывается функция потомка. ClassName - тоже = 'TMyClass'.
То есть, у нас определенно создался потомок, несмотря на то, что его конструктор не отработал.
Но! Т.к. конструктор не отработал, то в MyName находится данные родителя.
Это всего лишь пример. А в реале мне нужно в потомке создавать объекты в конструкторе.
Объекты не создаются, а в функционале потомка идет к ним обращения.
Вот и мучаюсь.
Выход вроде простой - создать функции Init и Done.
Но с объектной точки зрения это бред, т.к. для этого и преднозначен конструктор.
Да и вообще интересно, почему именно так? Почему создается потомок, все функции потомка, а конструктор предка?
Добавлено @ 15:07
Замечено, что если:
Код
function CreateNewClass(ClassId: TClasses):TCustomClass;
begin
  result := ClassId.Create;
end;
заменить на
Код
function CreateNewClass(ClassId: TClasses):TCustomClass;
begin
  result := TMyClass.Create;
end;
, то все отрабатывает правильно.
Но мне пока не известно, какого именно потомка я буду создавать.
Для этого и передаю класс потомка, как параметр.
Все отлично, все отрабатывает корректно, кроме конструктора. Why?

Автор: Bose 23.1.2006, 15:13
а может так?

Код

  TMyClass = class(TCustomClass) // потомок. В примере только один    
    constructor Create; override;// override или overload...
    function SayYourName: string; override; // метод    
  end;

Автор: Snowy 23.1.2006, 15:16
Нет, override только для виртуальных методов. А конструктор статичный.
Добавлено @ 15:19
Во как.
Сделал конструктор виртуальным, а у потомка сделал override.
Заработало!!!
Хм. Нужно будет подумать...
Спасибо, с меня жирный +

Автор: Bose 23.1.2006, 15:44
сам когда-то столкнулся с подобным smile

как вариант еще можно попробовать обьявить конструктор с overload. кажется должно сработать. насколько такое обьявление корректно - того не знаю не ведаю smile

Автор: Snowy 23.1.2006, 15:57
Нет, оверлоад тут совсем не к месту. Он нужен при наличии нескольких конструкторов. А у меня один.
А вот виртуальный конструктор - самое то.

Автор: Bose 23.1.2006, 16:00
ну да.... у меня в общем-то и было несколько конструкторов. Но дело в том, что оверлоад также позволяет вызвать конструктор потомка для статично обьявленного конструктора предка. (если я ничего не путаю).

Автор: Snowy 23.1.2006, 16:12
Цитата(Bose @ 23.1.2006, 16:00 Найти цитируемый пост)
Но дело в том, что оверлоад также позволяет вызвать конструктор потомка для статично обьявленного конструктора предка.

Неа. Не вызывает. Пробовал.

Автор: Bose 23.1.2006, 16:28
значит путаю smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)