Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.006 c
1-73297
Neon_space
2002-05-11 17:12
2002.05.23
Конвертирование проектов Delphi в проекты C++ Builder


1-73189
Цикл
2002-05-14 10:23
2002.05.23
Как грамотно прервать работу цикла ?


1-73317
Mikeee
2002-05-12 13:17
2002.05.23
Как убрать строку из ListBox-a...


14-73363
Kozhanov
2002-04-15 11:24
2002.05.23
Поддержка программой нескольких языков


1-73137
MisterBin
2002-05-12 09:43
2002.05.23
Чтобы было не видно курсора в поле ввода





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский