Страницы

Поиск по вопросам

воскресенье, 7 апреля 2019 г.

Абстрактные классы в Delphi

Допустим, есть базовый класс. В нем объявляем 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.

Комментариев нет:

Отправить комментарий