Форум: "Основная";
Текущий архив: 2002.05.23;
Скачать: [xml.tar.bz2];
Внизработа с полиморфными потоками в делфи Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.01 c