Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.10.14;
Скачать: CL | DM;

Вниз

Адрес метода класса :)   Найти похожие ветки 

 
Pa5ha ©   (2007-09-23 00:51) [0]

Тема звучит обсурдно. Не знал как назвать.

В общем написал класс (на самом деле object, но не суть) "автомат", который являет собой конечный автомат. Все бы хорошо, но для каждой надстройки нужен свой "драйвер", работающий с данными и обрабатывающий состояния, поэтому в автомат при инициализации передается адрес процедуры-драйвера, которая вызваеца при смене состояния и выполняет необходимые действия. Надстройка - парсер xml или просто парсер файла настроек невозможно обернуть в класс или объект из-за того что метод класса или объекта один на все экземпляры и следовательно нам нужна реальная процедура-обработчик-драйвер, которую в свою очередь можно привязать только к экземпляру.

собственно не знаю как решить данную проблему, кроме как запихать все в один класс. Но такое решение мне не очень нравица ибо неудобно. Мб кто делал подобное? )


 
Джо ©   (2007-09-23 02:40) [1]

Конечно, никто не мешает воспользоваться «адресом метода класса».
Но не лучше ли использовать возможности языка и обратиться к процедурным типам. Например, так:
type
 TSomeMethod = procedure (SomeParam: TSomeType) of object.
Или вообще использовать в качестве «драйвера» абстрактный класс или интерфейс.


 
Юрий Зотов ©   (2007-09-23 11:59) [2]

> Pa5ha ©   (23.09.07 00:51)

Одна из возможных схем:

type
 TAutomat = class(...)
 protected
   procedure StateChanged(...); virtual; abstract;
 public
   constructor Create(...); virtual;
   procedure ReadInput(...);
 end;

 TAutomatClass = class of TAutomat;

 TXMLParser = class(TAutomat)
 protected
   procedure StateChanged(...); override;
 end;

 TSettingsParser = class(TAutomat)
 protected
   procedure StateChanged(...); override;
 end;

==============

constructor TAutomat.Create(...);
begin
 inherited Create(...);
 ...
end;

procedure TAutomat.ReadInput(...);
begin
 ...
 StateChanged(...);
 ...
end;

procedure TXMLParser.StateChanged(...);
begin
 ...
end;

procedure TSettingsParser.StateChanged(...);
begin
 ...
end;


 
Юрий Зотов ©   (2007-09-23 12:17) [3]

> Pa5ha ©   (23.09.07 00:51)

Добавление к [2].

Создавать нужный экземпляр надстройки можно, например, так:

const
 ParserCount = 2;
 Extensions: array[0..(ParserCount -1)] of string =
   ("XML", "INI");
 ParserClasses: array[0..(ParserCount -1)] of TAutomatClass =
   (TXMLParser, TSettingsParser);

function CreateParser(const FileName: string; ...);
var
 Ext: string;
 i: integer;
begin
 Ext = AnsiUpperCase(ExtractFileExt(FileName));
 for i := 0 to ParserCount - 1 do
   if Extensions[i] = Ext then
   begin
     Result := ParserClasses[i].Create(...);
     Exit
   end
 raise
   Exception.CreateFmt("Класс парсера для расширения %s не найден", [Ext])
end;


 
b z   (2007-09-23 16:15) [4]


> function CreateParser(const FileName: string; ...);

и компилятор это пропускает?


 
Zeqfreed ©   (2007-09-23 16:20) [5]

> b z   (23.09.07 16:15) [4]

Разумеется. Если через препроцессор пропустить.


 
DrPass ©   (2007-09-23 16:21) [6]


> и компилятор это пропускает?

Пропускает, конечно. Ты что, правил Паскаля не знаешь?


 
Юрий Зотов ©   (2007-09-23 16:51) [7]

> b z   (23.09.07 16:15) [4]

Зависит от того, у кого какой компилятор. Некоторые - не пропускают.
:о)


 
Pa5ha ©   (2007-09-23 17:27) [8]

О, как здорово и оперативно ) Спсип, щас будем рыть в новосм направлении.


 
Юрий Зотов ©   (2007-09-23 17:58) [9]

Чтобы компилятору было полегче:
function CreateParser(const FileName: string; ...): TAutomat;
:o)


 
Kolan ©   (2007-09-23 20:43) [10]

> Юрий Зотов ©   (23.09.07 12:17)


> Extensions: array[0&#133(ParserCount —1)] of string =
>   ("XML", "INI");
> ParserClasses: array[0&#133(ParserCount —1)] of TAutomatClass
> =
>   (TXMLParser, TSettingsParser);

А мне не очень нравится что расширение почти не связано с классом. Имхо нужное расширение должно находится прямо в классе.
Может придложете другое решение?

Я предлогаю так:

TAutomat = class(&#133)
protected
  procedure StateChanged(&#133); virtual; abstract;
public
  constructor Create(&#133); virtual;
  procedure ReadInput(&#133);
  class function GetExtension: string;
end;



ParserClasses: array[0&#133(ParserCount —1)] of TAutomatClass =
  (TXMLParser, TSettingsParser);

function CreateParser(const FileName: string; &#133);
var
Ext: string;
i: integer;
begin
Ext = AnsiUpperCase(ExtractFileExt(FileName));
for i := 0 to ParserCount — 1 do
  if Extensions[i] = ParserClasses.Extension then
  begin
    Result := ParserClasses[i].Create(&#133);
    Exit
  end
raise
  Exception.CreateFmt("Класс парсера для расширения %s не найден", [Ext])
end;


 
Юрий Зотов ©   (2007-09-23 21:42) [11]

> Kolan ©   (23.09.07 20:43) [10]

1. В коде 2 ошибки, но это мелочь.

2. Один класс может обслуживать и несколько расширений, но это тоже мелочь.

3. А может и не обслуживать ни одного (ведь входные данные не обязаны находиться обязательно в файле). И с точки зрения проектирования классов это уже не мелочь, потому что метод GetExtension в базовом классе тогда становится совершенно нелогичным, потому что он предполагает хранение данных именно в файле. Поэтому у меня его в базовом классе и нет.


 
Kolan ©   (2007-09-23 21:56) [12]

> И с точки зрения проектирования классов это уже не мелочь,
> потому что метод GetExtension в базовом классе

Согласен не продумал. Но хранить исходные данные, помогающие выбрать какой класс надо инстанцировать, имхо, должны быть в самом классе&#133

Тогда дальше думать нельзя. Надо изучить все возможные способы хронения. Или вы предлогаете сделать для обсалютно неизвестного источника данных?
В любом случае можно переименовать GetExtension во что-то подходящее для всех случаев.


 
Юрий Зотов ©   (2007-09-23 22:20) [13]

> Kolan ©   (23.09.07 21:56) [12]

> хранить исходные данные, помогающие выбрать какой класс надо
> инстанцировать, имхо, должны быть в самом классе…

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

> Тогда дальше думать нельзя. Надо изучить все возможные способы
> хронения.

Совершенно верно. А это знает только автор вопроса. Поэтому я дальше думать и не стал, а просто дал одну из возможных схем. Остальное автор и сам доработает, как ему нужно.



Страницы: 1 вся ветка

Текущий архив: 2007.10.14;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.021 c
2-1189680614
CheckIT
2007-09-13 14:50
2007.10.14
Уменьшение разрешения картинки


2-1190221258
Jimmy
2007-09-19 21:00
2007.10.14
Имплонтация мультимедийного таймера в свой компонент


2-1190112357
xorload
2007-09-18 14:45
2007.10.14
предача и возврат данных dll


15-1189762734
vladislavmsk
2007-09-14 13:38
2007.10.14
Специальный TGroupBox


6-1171145538
batya18
2007-02-11 01:12
2007.10.14
SSH в Delphi