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

Вниз

работа с полиморфными потоками в делфи   Найти похожие ветки 

 
chsv ©   (2002-05-07 21:34) [0]

Раньше в Turbo Pascal"е в библиотеке Turbo Vision была такая возможность -- разработанные объекты можно было сохранять и загружать из потоков. Например, можно было создать свой тип данных TData (от TObject, разумеется), определить для него методы, выполняющие сохранение/загрузку данных в поток, зарегистрировать TData (кажется, это называлось RegisterObject, точно не помню), и все -- библиотека "умела" выгружать и загружать данные типа TData в поток и из потока. Можно было определить контруктор (кажется, Load()), который создавал и инициализировал объект из полиморфного потока. Load() разбирался, какого фактического типа объект нужно создать, создавал экземпляр объекта и инициализировал его данными из потока.
Вопрос -- как создавать аналогичные полиморфные потоки в делфи, чтобы не приходилось вручную сохранять информацию о типе пользовательского объекта в потоке (например, целочисленным кодом), как это приходилось делать "до полиморфизма".
В TStream и его потомках я что-то ничего похожего не нашел.


 
MBo ©   (2002-05-08 07:16) [1]

для этого наследуй от TPersistent


 
chsv ©   (2002-05-12 16:30) [2]

а писать-то в поток чем?


 
chsv ©   (2002-05-13 19:52) [3]

Предлагаю следующий способ создания полиморфных потоков. Не знаю, насколько правильно я использую делфи, но данные способ работает. (Хочется, чтобы кто-нибудь более искушенный в программировании на делфи прокомментировали его).

Суть способа состоит в том, что пользовательские типы наследуются от TComponent (см. FiguresUnit), в каждом пользовательском типе перекрываются методы

procedure ReadState(Reader: TReader);
procedure WriteState(Writer: TWriter).

Реализация ReadState() и WriteState() в каждом пользовательском типе вызывает соответствующий метод родителя, затем выполняет соответственно чтение или запись собственных данных (см. реализацию в TRectangle и в TCircle). Чтобы считывать данные из потока, необходимо зарегистрировать пользовательские типы с помощью процедуры RegisterClasses(). Я помесстил ее в раздел initialization модуля FiguresUnit:

initialization
RegisterClasses( [TFigure, TRectangle, TCircle] ).

Модуль ListFiguresUnit реализует полиморфный список фигур, "умеющий" сохранять и загружать данные в поток и из потока. Для записи/чтения фигуры вызывается метод WriteComponent() и ReadComponent() соответственно (см. TFiguresList.save_stream() и TFiguresList.load_stream()).


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////


unit FiguresUnit;

interface
uses Classes, Windows;

type
TFigure = TComponent;

TRectangle = class ( TFigure )
private
v_left_top : TPoint;
v_right_bottom : TPoint;
public
procedure ReadState(Reader: TReader); override;
procedure WriteState(Writer: TWriter); override;
constructor create( const a_left_top, a_right_bottom : TPoint );
end;

TCircle = class ( TFigure )
private
v_center : TPoint;
v_radius : integer;
public
procedure ReadState(Reader: TReader); override;
procedure WriteState(Writer: TWriter); override;
constructor create( const a_center : TPoint; a_radius : integer = 30 );
end;


implementation


{ TRectangle }

constructor TRectangle.create( const a_left_top, a_right_bottom : TPoint );
begin
inherited create( nil );
v_left_top := a_left_top;
v_right_bottom := a_right_bottom
end;

procedure TRectangle.ReadState(Reader: TReader);
begin
inherited;
Reader.Read( v_left_top, sizeof( v_left_top ));
Reader.Read( v_right_bottom, sizeof( v_right_bottom ));
end;

procedure TRectangle.WriteState(Writer: TWriter);
begin
inherited;
Writer.write( v_left_top, sizeof( v_left_top ));
Writer.write( v_right_bottom, sizeof( v_right_bottom ));
end;


{ TCircle }

constructor TCircle.create( const a_center : TPoint; a_radius : integer = 30 );
begin
inherited create( nil );
v_center := a_center;
v_radius := a_radius
end;

procedure TCircle.ReadState(Reader: TReader);
begin
inherited;
Reader.Read( v_center, sizeof( v_center ));
Reader.Read( v_radius, sizeof( v_radius ))
end;

procedure TCircle.WriteState(Writer: TWriter);
begin
inherited;
Writer.write( v_center, sizeof( v_center ));
Writer.write( v_radius, sizeof( v_radius ))
end;


initialization
RegisterClasses( [TFigure, TRectangle, TCircle] );

end. // FiguresUnit



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////



unit ListFiguresUnit;

interface
uses classes;

type
TFiguresList = class( TList )
public
destructor destroy; override;
procedure erase_all;
procedure save_stream( const a_stm : TStream );
procedure load_stream( const a_stm : TStream );
end;



implementation
uses FiguresUnit;


{ TFiguresList }

destructor TFiguresList.destroy;
begin
erase_all;
inherited
end;

procedure TFiguresList.erase_all;
var
i : integer;
begin
for i := count - 1 downto 0 do begin
TFigure( items[ i ] ).free;
items[ i ] := nil;
delete( i )
end;
pack
end;

procedure TFiguresList.save_stream( const a_stm : TStream );
var
i : integer;
begin
a_stm.Write(count, sizeof( count ));
for i := 0 to count - 1 do
a_stm.WriteComponent( items[ i ] )
end;

procedure TFiguresList.load_stream( const a_stm : TStream );
var
i : integer;
a_count : integer;
begin
erase_all;
a_stm.read(a_count, sizeof( a_count ));
for i := 0 to a_count - 1 do
add( a_stm.ReadComponent( nil ) )
end;


end. // ListFiguresUnit


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////



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

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

Наверх




Память: 0.49 MB
Время: 0.013 c
1-73305
Servis
2002-05-11 22:14
2002.05.23
О формах в DLL


1-73299
Dion
2002-05-11 21:03
2002.05.23
Помогите определить по таймеру настоящее время суток в программе


3-73086
Tanya
2002-04-29 09:41
2002.05.23
Reports


4-73461
medan
2002-03-18 12:06
2002.05.23
закрытие всех окон без вопросов


1-73172
CybVe
2002-05-13 16:53
2002.05.23
Что такое TFrame и зачем он нужен?