Допустим, есть базовый класс. В нем объявляем abstract virtual функцию. В наследнике реализуем эту функцию (перекрываем override). Вопрос: можно ли вызывать эту функцию в базовом классе? ПС: Спрашиваю потому, что встретился с такой ситуацией в чужом коде. До этого думал, что это невозможно.
Ответ
Можно. Смысл в том, что экземпляров базового абстрактного класса у вас никогда не будет. Будет экземпляр конкретного дочернего класса, в котором этот метод точно переопределен.
Этот шаблон проектирования, кстати, называется Шаблонный метод (Template method): в базовом абстрактном классе мы собираем некоторый алгоритм из абстрактных методов. И уже от дочерних конкретных классов будет зависеть работа этого алгоритма.
Пример: в базовом классе TCocktail определяется процедура приготовления коктейля. Дочерние классы реализуют конкретные этапы этого процесса.
Базовый класс:
type
TCocktail = class
protected
procedure AddFirstIngridient(); virtual; abstract; //Добавление первого ингридиента
procedure AddSeconsIngridient(); virtual; abstract; //Добавление второго ингридиента
procedure AddDecorations(); virtual; abstract; //Добавление украшений
function GetName(): string; virtual; abstract; //Название
public
procedure Prepare; //Алгоритм приготовления коктейля
end;
{ TCocktail }
procedure TCocktail.Prepare;
begin
writeln('Готовим коктейль ' + GetName());
AddFirstIngridient();
AddSeconsIngridient();
AddDecorations();
writeln('Ваш коктейль готов');
end;
Первый коктейль
type
TBloodyMary = class (TCocktail)
protected
procedure AddFirstIngridient();override;
procedure AddSeconsIngridient();override;
procedure AddDecorations();override;
function GetName(): string;override;
end;
{ TBloodyMary }
procedure TBloodyMary.AddDecorations;
begin
writeln('Добавляем лед');
end;
procedure TBloodyMary.AddFirstIngridient;
begin
writeln('50мл водки');
end;
procedure TBloodyMary.AddSeconsIngridient;
begin
writeln('150мл томатного сока');
end;
function TBloodyMary.GetName: string;
begin
result := 'Кровавая Мэри';
end;
Второй коктейль
type
TIrishCoffee = class (TCocktail)
protected
procedure AddFirstIngridient();override;
procedure AddSeconsIngridient();override;
procedure AddDecorations();override;
function GetName(): string;override;
end;
{ TBloodyMary }
procedure TIrishCoffee.AddDecorations;
begin
writeln('50 сливки (33%)');
end;
procedure TIrishCoffee.AddFirstIngridient;
begin
writeln('50мл ирландского виски');
end;
procedure TIrishCoffee.AddSeconsIngridient;
begin
writeln('80мл кофе');
end;
function TIrishCoffee.GetName: string;
begin
result := 'Ирландский кофе';
end;
Ну и сам код:
var cocktail: TCocktail;
begin
cocktail := TBloodyMary.Create;
cocktail.Prepare;
cocktail := TIrishCoffee.Create;
cocktail.Prepare;
readln;
end.
Комментариев нет:
Отправить комментарий