2015-03-02 3 views
3

В базовом классе есть виртуальный метод, который переопределяется в подклассе.Delphi: следует ли использовать перегрузку, повторно вводить + перегрузку или нет?

Однако мне нужно добавить новый параметр в метод подкласса, и невозможно использовать объявление переопределения, так как параметры разные.

Пример:

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

    TApple = class(TFruit) 
    public 
    constructor Create(Color: TColor); override; // Error: Declaration of 'Create' differs from previous declaration 
    end; 

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

Тогда я подумал об использовании «перегрузки», но тогда я не могу использовать «переопределить» вместе. Поэтому я спрашиваю: есть ли какие-либо проблемы только при использовании «перегрузки»? (Delphi показывает предупреждение: метод «Создать» скрывает виртуальный метод базового типа «TFruit»)

Я также проверил использование повторной установки + перегрузки (чтобы скрыть предупреждение выше), но я также видел плохие рекомендации относительно этой практики , Как вы думаете?

И последнее, что, если я просто не использую ни один из них, просто удалив «переопределить» в методе подкласса и добавлю новый параметр? (что дает мне такое же предупреждение)

У кого-нибудь есть предложения о том, что я должен делать в этом случае, чтобы сохранить хорошие практики?

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

    TApple = class(TFruit) 
    public 
    constructor Create; override; 

    // What should I do: 
    // constructor Create(Color: TColor); overload; // Shows a warning 
    // constructor Create(Color: TColor); reintroduce; overload; // Hides the warning 
    // constructor Create(Color: TColor); // Shows a warning 
    // Other solution? 
    end; 

Спасибо!

+1

у вас есть много Bigge r проблема. Использование виртуального конструктора подразумевает, что вы хотите создать экземпляр из метакласса. Это означает, что у вас должен быть только один конструктор, виртуальный, потенциально переопределенный в производных классах. –

+1

Re (edit): Конструктор или нет, уже ответ на него уже отвечает. Если вы не можете переопределить, вызов CodToDesc в переменной TBaseClass, указывающий на экземпляр TSubClass, не будет запускать TSubClass.CodToDesc. Вот и все. –

+0

@Roberto Относительно вашего редактирования: поскольку уже предоставленный и сильно поддержанный ответ касается конструктора, как ваш первоначальный вопрос задал вопрос, я советую отменить редактирование и задать новый вопрос, возможно, ссылаясь на этот вопрос. – NGLN

ответ

12

Конструкторы в Дельфах не должны называться Create(). Их можно назвать тем, что вы хотите. Так что, если вам нужно ввести новый параметр, и это влияет только несколько строк кода, я предложил бы создать целый новый конструктор:

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

    TApple = class(TFruit) 
    public 
    constructor CreateWithColor(Color: TColor); 
    end; 

constructor TApple.CreateWithColor(Color: TColor); 
begin 
    inherited Create; 
    // use Color as needed... 
end; 

Большинство кода все равно будет в состоянии назвать TApple.Create(), и несколько затронутых линий могли бы позвонить TApple.CreateWithColor().

В противном случае, используйте reintroduce, если у вас есть, чтобы сохранить имя Create(), и дать ему параметр по умолчанию, так существующий код будет компилироваться:

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

    TApple = class(TFruit) 
    public 
    constructor Create(Color: TColor = clNone); reintroduce; 
    end; 

constructor TApple.Create(Color: TColor); 
begin 
    inherited Create; 
    // use Color as needed... 
end; 

Просто знаю, что в любом случае, если вы создаете производные экземпляры объектов используя class of TFruit метакласса (что является обычной причиной для virtual конструктора), вы не будете иметь возможности вызывать либо пользовательский TApple конструктор:

type 
    TFruit = class(TObject) 
    public 
    constructor Create; virtual; 
    end; 
    TFruitClass = class of TFruit; 

    TApple = class(TFruit) 
    public 
    constructor Create(Color: TColor = clNone); reintroduce; 
    // constructor CreateWithColor(Color: TColor); 
    end; 

var 
    Fruit: TFruit; 
    Cls: TFruitClass; 
begin 
    Cls := TApple; 
    Fruit := Cls.Create; // calls TFruit.Create() since it is not overridden in TApple... 
    //... 
end; 
+0

Виртуальный конструктор обычно воспринимается как указание на то, что класс может быть создан посредством метакласса. Представленные здесь варианты несовместимы. –

+0

@DavidHeffernan: Я это знаю. Я добавил его к моему ответу. –

+0

Спасибо. Я знаю, что вы это знаете. ;-) –

Смежные вопросы