Я хочу понять
- виртуальный
- переопределить
- перегрузка
- реинтродукции
при применении к конструкторам объектов. Каждый раз, когда я произвольно добавляю ключевые слова до тех пор, пока компилятор не закроется - и (после 12 лет разработки с Delphi), я бы лучше знал, что я делаю, а не пытался случайным образом.
Учитывая гипотетический набор объектов:
TComputer = class(TObject)
public
constructor Create(Cup: Integer); virtual;
end;
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer; Teapot: string); virtual;
end;
TiPhone = class(TCellPhone)
public
constructor Create(Cup: Integer); override;
constructor Create(Cup: Integer; Teapot: string); override;
end;
То, как я хочу, чтобы они вели себя, вероятно, очевидно из деклараций, но:
-
TComputer
имеет простой конструктор, и потомки могут его переопределить -
TCellPhone
имеет альтернативный конструктор, и потомки могут его переопределить -
TiPhone
переопределяет оба конструктора, вызывая унаследованную версию каждого
Теперь этот код не компилируется. Я хочу понять, почему это не работает. Я также хочу понять правильный способ переопределения конструкторов. Или, возможно, вы никогда не сможете переопределить конструкторы? Или, возможно, вполне приемлемо переопределить конструкторы? Возможно, у вас никогда не должно быть нескольких конструкторов, возможно, вполне приемлемо иметь несколько конструкторов.
Я хочу понять, почему. Тогда это будет очевидно.
См. также
- Delphi: Как скрыть конструкторы предков?
- Повторное введение функций в Delphi
- Delphi: как добавить другой конструктор к потомку?
Изменить: Я также хочу получить некоторые рассуждения о порядке virtual
, override
, overload
, reintroduce
. Потому что при попытке всех комбинаций ключевых слов число комбинаций взрывается:
- виртуальный; перегрузки;
- виртуальный; переопределить;
- переопределение; перегрузки;
- переопределение; виртуальный;
- виртуальный; переопределить; перегрузки;
- виртуальный; перегрузки; переопределить;
- перегрузки; виртуальный; переопределить;
- переопределение; виртуальный; перегрузки;
- переопределение; перегрузки; виртуальный;
- перегрузки; переопределить; виртуальный;
- и т.д.
Изменить 2: Я думаю, мы должны начать с "является ли возможна иерархия объектов? Если нет, почему бы и нет? Например, принципиально неверно иметь конструктор от предка?
TComputer = class(TObject)
public
constructor Create(Cup: Integer); virtual;
end;
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer; Teapot: string); virtual;
end;
я бы ожидал, что TCellPhone
теперь имеет два конструктора. Но я не могу найти комбинацию ключевых слов в Delphi, чтобы заставить его думать, что это действительно важно. Я принципиально ошибаюсь, думая, что у меня могут быть два конструктора в TCellPhone
?
Примечание. Все, что находится ниже этой строки, строго не требуется для ответа на вопрос - но это помогает объяснить мое мышление. Возможно, вы можете видеть, основанные на моих мысленных процессах, что фундаментальная часть, которую я пропускаю, делает все ясно.
Теперь эти объявления не компилируются:
//Method Create hides virtual method of base type TComputer:
TCellPhone = class(TComputer)
constructor Create(Cup: Integer; Teapot: string); virtual;
//Method Create hides virtual method of base type TCellPhone:
TiPhone = class(TCellPhone)
public
constructor Create(Cup: Integer); override;
constructor Create(Cup: Integer; Teapot: string); overload; <--------
end;
Итак, сначала я попытаюсь установить TCellPhone
. я начну с случайного добавления ключевого слова overload
(я знаю, что не хочу reintroduce
, потому что это скроет другой конструктор, который я не хочу):
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer; Teapot: string); virtual; overload;
end;
Но это не удается: Field definition not allowed after methods or properties
.
Я знаю по опыту, что даже если у меня нет поля после метода или свойства, если я отменил порядок ключевых слов virtual
и overload
: Delphi закроется:
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;
Но я все еще получаю ошибку:
Метод "Создать" скрывает виртуальный метод базового типа "TComputer"
Итак, я пытаюсь удалить оба ключевых слова:
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer; Teapot: string);
end;
Но я все еще получаю ошибку:
Метод "Создать" скрывает виртуальный метод базового типа "TComputer"
Итак, я схожу, чтобы теперь попробовать reintroduce
:
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer; Teapot: string); reintroduce;
end;
И теперь TCellPhone компилируется, но для TiPhone это намного хуже:
TiPhone = class(TCellPhone)
public
constructor Create(Cup: Integer); override; <-----cannot override a static method
constructor Create(Cup: Integer; Teapot: string); override; <-----cannot override a static method
end;
Оба жалуются, что я не могу их переопределить, поэтому я удаляю ключевое слово override
:
TiPhone = class(TCellPhone)
public
constructor Create(Cup: Integer);
constructor Create(Cup: Integer; Teapot: string);
end;
Но теперь второе создание говорит, что оно должно быть отмечено перегрузкой, которую я делаю (на самом деле я буду отмечать как перегрузку, так как знаю, что произойдет, если я этого не сделаю):
TiPhone = class(TCellPhone)
public
constructor Create(Cup: Integer); overload;
constructor Create(Cup: Integer; Teapot: string); overload;
end;
В разделе interface
все хорошо. К сожалению, мои реализации не будут работать. Мой единственный конструктор параметров TiPhone не может вызвать унаследованный конструктор:
constructor TiPhone.Create(Cup: Integer);
begin
inherited Create(Cup); <---- Not enough actual parameters
end;