Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.10.14;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.037 c
15-1189870254
ЭРИКА
2007-09-15 19:30
2007.10.14
С ДНЕМ РОЖДЕНИЯ КАЙ


15-1189701129
vasIZmax
2007-09-13 20:32
2007.10.14
DMClient


15-1189970382
ProgRAMmer Dimonych
2007-09-16 23:19
2007.10.14
Посоветуйте, что делать


2-1189763330
artem779
2007-09-14 13:48
2007.10.14
как изменить имя проекта ?


2-1190529112
zavialov
2007-09-23 10:31
2007.10.14
Не увеличивать счетчик ссылок - создать отдельный экземпляр.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский