Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Реализация подпрограммы в дочернем классе


Автор: Keeper89 9.8.2010, 13:52
Доброго времени суток.

Имеется класс TProblem с методом Solve:
Код

var
  FSolution: Real;

procedure TProblem.Solve();
begin
  FTime = GetTickCount;

  MainSolveRoutine();

  FTime = GetTickCount - FTime;
end;

где MainSolveRoutine реализуется потомком (например Problem1 = class(TProblem)), и полученный в ней результат должен возвращаться в FSolution.

Правильна и возможна ли такая структура? Стоит ли и есть ли возможность ее улучшить?

Спасибо.

Автор: Frees 9.8.2010, 14:47
Цитата(Keeper89 @  9.8.2010,  16:52 Найти цитируемый пост)
Правильна и возможна ли такая структура? Стоит ли и есть ли возможность ее улучшить?

правильна, для этого придуманы virtual методы - вызов метода потомка из родителя

Добавлено @ 14:48
имеет смысл если таких потомков несколько и у каждого своя реализация MainSolveRoutine(); 

Автор: Keeper89 9.8.2010, 14:52
Frees, ок. А как тогда реализовать дочернюю процедуру с возвращением значений в родительский FSolution?

Автор: Frees 9.8.2010, 14:54
Цитата(Keeper89 @  9.8.2010,  17:52 Найти цитируемый пост)
А как тогда реализовать дочернюю процедуру с возвращением значений в родительский FSolution

не совсем понял что такое  FSolution
понял

FSolution не принадлежит классу, поэтому она везде будет иметь одно и  тоже значение..

Добавлено через 3 минуты и 57 секунд
FSolution - сделай полем класса TProblem  и пиши в нее, в потомках из нее можешь читать...

Автор: Qu1nt 9.8.2010, 15:25
Код

FSolution := MainSolveRoutine;

Кстати, тип Real - устаревший. Используй Double.

Автор: Keeper89 9.8.2010, 16:09
Qu1nt, я его и использую, это просто для примера.

Автор: pseud 10.8.2010, 13:58
Keeper89, ну как бы так...
Код

type
  TProblem = class
  private
    procedure Solve;
  protected
    procedure MainSolveRoutine; virtual; abstract;
  public
    FSolution: Double;
  end;

type
  TBigProblem = class(TProblem)
  protected
    procedure MainSolveRoutine; override;
  end;

{ TBigProblem }

procedure TBigProblem.MainSolveRoutine;
begin
  FSolution := 77.77;
end;

{ TProblem }

procedure TProblem.Solve;
begin
  MainSolveRoutine;
  if FSolution = 77.77 then;
end;


проверка:
Код

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TBigProblem.Create do
  try
    Solve;
    ShowMessage(FloatToStr(FSolution));
  finally
    Free;
  end;
end;

Автор: Keeper89 10.8.2010, 16:14
pseud, спасибо, утром реализовал как раз такую вещь smile

Автор: Keeper89 11.8.2010, 01:11
Вопрос в тему. Если во втором случае перенести
Код

MainSolveRoutine

из protected в private, будут соответствующие ворнинги.
Стоит так делать или лучше оставить в protected?

Автор: pseud 11.8.2010, 09:54
Цитата(Keeper89 @  11.8.2010,  01:11 Найти цитируемый пост)
из protected в private, будут соответствующие ворнинги.
Стоит так делать или лучше оставить в protected?

варнингов не будет, будет лишь хинт:
Цитата

[Hint] Unit1.pas(22): Overriding virtual method 'TBigProblem.MainSolveRoutine' has lower visibility (private) than base class 'TProblem' (protected)

А какой смысл переносить в private? Только если ты планируешь создавать классы-наследники TBigProblem, описываемые в других модулях, и в них ну совсем нельзя переопределять метод MainSolveRoutine.
Понижать видимость не принято.

Автор: Keeper89 11.8.2010, 23:51
Цитата(pseud @  11.8.2010,  09:54 Найти цитируемый пост)
Понижать видимость не принято. 

Ok, спасибо.

Автор: cat512 20.8.2010, 23:04
Цитата(pseud @ 10.8.2010,  13:58)
Keeper89, ну как бы так...
Код

type
  TProblem = class
  private
    procedure Solve;
  protected
    procedure MainSolveRoutine; virtual; abstract;
  public
    FSolution: Double;
  end;

type
  TBigProblem = class(TProblem)
  protected
    procedure MainSolveRoutine; override;
  end;

{ TBigProblem }

procedure TBigProblem.MainSolveRoutine;
begin
  FSolution := 77.77;
end;

{ TProblem }

procedure TProblem.Solve;
begin
  MainSolveRoutine;
  if FSolution = 77.77 then;
end;


проверка:
Код

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TBigProblem.Create do
  try
    Solve;
    ShowMessage(FloatToStr(FSolution));
  finally
    Free;
  end;
end;

А что мешает использовать FSolution в секции Private?

Автор: pseud 23.8.2010, 09:09
Цитата(cat512 @  20.8.2010,  23:04 Найти цитируемый пост)
А что мешает использовать FSolution в секции Private?

напрмер, вот это:
Код

procedure TForm1.Button1Click(Sender: TObject);
begin
  ...
  ShowMessage(FloatToStr(FSolution));
  ...
end;

Автор: cat512 23.8.2010, 12:52
Ну так сделай свойство у класса
Код

private
  FSolution: double;
public
  property Solution: double read FSolution write FSolution;
 
И юзай его другим классом. Предыдущими примерами ты нарушаеш инкапсуляцию

Автор: pseud 23.8.2010, 14:24
ОФФ
Цитата(cat512 @  23.8.2010,  12:52 Найти цитируемый пост)
И юзай его другим классом. Предыдущими примерами ты нарушаеш инкапсуляцию

во-первых, не я держатель темы.
во-вторых, в теме поднят вопрос "Как намазать хлеб на масло?". А твой ответ звучит как "Масло нужно достать из холодильника, а не из шкафчика" 
в-третьих, тема давно решена и нет никакого смысла вываливать ее на верх раздела.

Добавлено через 6 минут и 46 секунд
а с полиморфизмом и наследованием я ничего хоть не напорол?

Автор: cat512 23.8.2010, 17:24
Цитата

а с полиморфизмом и наследованием я ничего хоть не напорол?

Сожалею, что моё мнение вызывает у тебя иронию. Не хочется вступать в дискуссию, но пожалуй отвечу. В теме был поднят вопрос:
Цитата

Правильна и возможна ли такая структура? Стоит ли и есть ли возможность ее улучшить?
 на который ты (надеюсь не обидишься что перешёл на ты) ответил imho частично.
Исходя из твоей аналогии с хлебом и маслом, вопрос звучит так:
"можно ли и как правильно мазать масло на хлеб?" А мой ответ прозвучал: "Масло нужно мазать на хлеб сверху а не снизу".
Такой стиль с Public полем обычно используется в проектах "писаных на коленках" Как правило такие проеты долго не живут. Ты в vcl много классов видел с public полями? Я не вижу ничего плохого в том что бы рассказать человеку об альтернативной конструкции, более правильной с точки зрения ооп, чтобы он приучался использовать таковые, а не плодить Public-поля.

Автор: Keeper89 24.8.2010, 09:21
Если уж вы перешли на масло, то маслом здесь был подход к реализации дочерней процедуры, а не в какой секции что объявить. 
pseud привет пример первого, что и нужно было. Что касается "правильности", у меня переменная стоит в private, хотя объявление свойства
Цитата(cat512 @  23.8.2010,  12:52 Найти цитируемый пост)
Ну так сделай свойство у класса

абсолютно идентично паблик переменной.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)