Форум: "Начинающим";
Текущий архив: 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…(ParserCount —1)] of string =
> ("XML", "INI");
> ParserClasses: array[0…(ParserCount —1)] of TAutomatClass
> =
> (TXMLParser, TSettingsParser);
А мне не очень нравится что расширение почти не связано с классом. Имхо нужное расширение должно находится прямо в классе.
Может придложете другое решение?
Я предлогаю так:TAutomat = class(…)
protected
procedure StateChanged(…); virtual; abstract;
public
constructor Create(…); virtual;
procedure ReadInput(…);
class function GetExtension: string;
end;
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] = ParserClasses.Extension then
begin
Result := ParserClasses[i].Create(…);
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 в базовом классе
Согласен не продумал. Но хранить исходные данные, помогающие выбрать какой класс надо инстанцировать, имхо, должны быть в самом классе…
Тогда дальше думать нельзя. Надо изучить все возможные способы хронения. Или вы предлогаете сделать для обсалютно неизвестного источника данных?
В любом случае можно переименовать 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