2013-06-29 1 views
0

Один с виртуальным/динамическимпереопределение, виртуальная/динамика в Delphi конструкторов

// declare in Child Class 
constructor Create; virtual; 

constructor TChildClass.Create; 
begin 
    inherited; 
end; 

Тот с отключением.

// declare in Child Class 
constructor Create; override; 

constructor TChildClass.Create; 
begin 
    inherited; 
end; 

Тот ничего

// declare in Child Class 
constructor Create; 

constructor TChildClass.Create; 
begin 
    inherited; 
end; 

ли это то же самое? Это выглядит запутанным.

+0

ли это Q имеет ничего общего с конструкторами, в частности, или с ООП в целом? –

+0

на самом деле, просто хочу знать разницу, определенную в этом примере delphi. –

+1

Было бы лучше, если бы вы не оставили угадывать игры в вопросе. Строки «// declare» - это часть базового класса или дочернего класса? Было бы лучше, если бы вы произвели полные, но минимальные примеры в каждом случае. –

ответ

1

Нет, статические и виртуальные методы - это не одно и то же.

И override - это случай virtual метод.

http://en.wikipedia.org/wiki/Virtual_function

http://docwiki.embarcadero.com/RADStudio/XE4/en/Methods#Method_Binding

Конструкторы не приносят ничего особенного здесь - они соответствуют тем же правилам, что и другие методы вопроса

+0

унаследованный может быть в конструкторе независимо от того, какие ключевые слова приходят после конструктора, не так ли? –

+0

Да. 'Inherited' просто вызывает метод класса предка, независимо от чего-либо в потомке. –

+0

@Rob: коррекция: в то время как это не актуально для конструкторов, в общем случае «унаследованный» вызывает метод предка **, если есть один ** и ничего не делает (нет-op) **, если его нет ** - это делает разница для методов 'abstract', –

5

Да, есть разница, но давайте рассмотрим ключевое слово virtual в более простых терминах ООП, но все же, как это относится к методам Delphi.

Когда вы объявляете производный (дочерний) класс и реализуете метод как «переопределить», это означает, что вы переопределяете (удивляете) метод сопоставления базового класса.

Это означает, что вы можете написать код так:

var child : TBaseClass; 
begin 
    child := TChildClass.Create; // note that it is stored in TBaseClass variable 
    child.VirtualMethodDefinedInBaseClassThatHasBeenOverriddenInChildClass; 

Это будет вызывать метод в дочернем классе, даже если переменная определена как типа базового класса. В этом и заключается цель виртуальных методов, вы можете получить доступ к объекту посредством ссылки более общего типа и по-прежнему вызывать методы, которые были написаны для определенного типа объекта, с которым вы имеете дело.

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

В принципе, если ваша переменная имеет тип TBaseClass и вы вызываете на ней виртуальный метод, который был повторно введен в TChildClass, он все равно вызовет метод в базовом классе.

Однако, если ваша переменная имеет тип TChildClass, и вы вызываете этот метод на нее, вместо этого вы получите новый метод.

Теперь, для конструкторов, в Delphi, это немного отличается.

Точка виртуальных конструкторов должна иметь возможность практически строить объекты, и для этого в Delphi также есть «типы классов».

Вы можете сказать следующее:

type TClassToUse = class of TBaseClass; 
var cls : TClassToUse; 
    obj : TBaseClass; 
begin 
    cls := TChildClass; 
    obj := cls.Create; 

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

Здесь мы храним «класс» в переменной, а затем попросим класс запросить конструкцию объекта для нас. Это позволяет нам отключить класс для создания, но нам также нужно объявить конструкторы, которые мы хотим использовать виртуальными, иначе у нас будут проблемы.

Таким образом, в приведенном выше коде, если вы объявили конструктор виртуальным в TBaseClass, а затем переопределите его в TChildClass (который фактически использует код в cls), переопределенный конструктор является тем, который будет использоваться.

Если, с другой стороны, вы не объявляете конструктор виртуальным, мы возвращаемся к конструктору базового класса. Виртуальный в основном означает вычисление правильного метода для выполнения во время выполнения, тогда как не виртуальный будет определять его во время компиляции.

Реинтродукция, как описано выше для нормальных методов, также работает таким образом.

Однако виртуальные конструкторы используются только как виртуальные при использовании по типу класса.

+1

+1. Хороший ответ. Так же, как FYI: Delphi действительно включает ключевое слово reintroduce для повторного введения, используемое при определении методов с тем же именем, но с разными параметрами, чем в родительском классе. –

+1

Повторное введение никогда не требуется, метод у предка просто скрыт. Однако, не используя повторное введение в метод, который является виртуальным (или динамическим) в предке, выдается предупреждение о том, что «метод X скрывает виртуальный метод X у предка A» (что-то вдоль этих строк). Поэтому, если вы хотите, чтобы ваши компиляции/сборки генерировали нулевые подсказки и предупреждения (что вам нужно), вам нужно будет повторно использовать. –

+0

@MarjanVenema, но это более необходимо. Думаю, в ранней версии скрытие считалось вредным, опасным и заслуживающим предупреждения в любом случае. Когда они решили сделать это законной, если экзотическая практика, они не смогли обеспечить ее соблюдение из-за обратной совместимости ... –