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

Вниз

Как инициализировать наследуемые поля абстрактных классов?   Найти похожие ветки 

 
Другой Дмитрий   (2005-06-30 09:05) [0]

Необходимо определить базовый класс компонента с абстрактным потоком и объявить в нем методы записи в него.
От этого компонента будут наследоваться компоненты, в которых реализованы потоки типа TFileStream и TMemoryStream.
Как правильнее описать создание потока в потомках? На ум приходи такое:


 TMyStreamComp = class(TObject)  {базовый класс}
   private
     FStream : TStream;
   protected
     constructor Create;
     destructor Destroy;
     procedure WriteToStream; virtual; abstract;
     procedure InitialStream(AStream : TStream); virtual; abstract;
 end;

 constructor TMyStreamComp.Create;
 begin
      inherited;
      InitialStream(FStream);
 end;

 destructor TMyStreamComp.Destroy;
 begin
      FStream.Free;
      inherited;
 end;

 TMyFileStreamComp = class(TMyStreamComp )
   private
     FStream : TStream;
   protected
     procedure WriteToStream; override;
     procedure InitialStream(AStream : TStream); override;
 end;

 constructor TMyStreamComp.InitialStream(AStream : TStream)
 begin
      AStream:=TFileStream.Create("file.txt",fmOpenRead);
 end;


Мне кажется это сильно притянуто за уши, как делать правильно?


 
Плохиш ©   (2005-06-30 09:12) [1]


> Другой Дмитрий   (30.06.05 09:05)

1. Создай свойство у своего класса, тогда пользователь сможет присваивать ему свой экземпляр стрима.
или
2. Создавай экземпляр того стрима, который тебе нужен для работы.


 
Другой Дмитрий   (2005-06-30 09:44) [2]

Все я наврал, вот так вижу:


unit Unit2;

interface

uses Classes;

type
TMyComp = class(TObject)  {базовый класс}
  protected
    procedure WriteBuffer(Buffer : Pointer; Count : integer); virtual; abstract;
end;

TMyStreamComp = class(TMyComp)  {базовый класс потоков}
  private
    FStream : TStream;
  protected
    constructor Create;
    destructor Destroy;
    procedure WriteBuffer(Buffer : Pointer; Count : integer); override;
    procedure InitialStream(AStream : TStream); virtual; abstract;
end;

TMyFileStreamComp = class(TMyStreamComp )
  protected
    procedure InitialStream(AStream : TStream); override;
end;

TMyMemoryStreamComp = class(TMyStreamComp )
  protected
    procedure InitialStream(AStream : TStream); override;
end;

implementation

{ TMyStreamComp }

constructor TMyStreamComp.Create;
begin
 inherited;
 InitialStream(FStream);
end;

destructor TMyStreamComp.Destroy;
begin
 FStream.Free;
 inherited;
end;

procedure TMyStreamComp.WriteBuffer(Buffer : Pointer; Count : integer);
begin
 FStream.Write(Buffer,Count);
end;

{ TMyFileStreamComp }

procedure TMyFileStreamComp.InitialStream(AStream: TStream);
begin
 AStream:=TFileStream.Create("file.txt",fmCreate);
end;

{ TMyMemoryStreamComp }

procedure TMyMemoryStreamComp.InitialStream(AStream: TStream);
begin
 AStream:=TMemoryStream.Create;
end;

end.



TMyFileStreamComp и TMyMemoryStreamComp не должны иметь никакого понятия как записывать в поток - это должно быть в базовом классе потоков. Как правильно инициализировать потоки?


 
GrayFace ©   (2005-06-30 12:27) [3]

InitialStreamне нужен. Итак есть Create. В Create потомков и создавый Stream. Не понимаю, в чем проблема?


 
Другой Дмитрий   (2005-06-30 13:20) [4]

Я чего думал, что FStream в TMyFileStreamComp и FStream базового класса TMyComp разные поля, тогда будет так?


constructor TMyFileStreamComp.Create;
begin
FStream:=TFileStream.Create("file.txt",fmCreate);
end;


или так?


constructor TMyFileStreamComp.Create;
begin
inherited FStream:=TFileStream.Create("file.txt",fmCreate);
end;


 
Digitman ©   (2005-06-30 13:43) [5]


> разные поля


зачем разные-то ?

и файлстрим и мемстрим - наследники стрима

достаточно объявить поле типа стрим в базовом классе - и все наследники баз.класса смогут ей воспользоваться


 
Другой Дмитрий   (2005-06-30 13:56) [6]

По моему, по логике - FStream приватное поле базового класса и если TMyFileStreamComp и TMyStreamComp разместить в разных модулях, то  у TMyFileStreamComp не будет доступ к FStream базового класса, а если в одном модуле, то TMyFileStreamComp видит поле FStream базового класса только лишь из-за особенностей реализации ООП Delphi. А как же по науке делают, например в каких -нибудь Си?


 
Digitman ©   (2005-06-30 14:00) [7]


> как же по науке делают, например в каких -нибудь Си?


причем здесь Си ?

"по науке" в ОР делаю так :
- либо выносят BaseClass.FStream в секцию protected
- либо BaseClass.FStream оставляют в секции private, но в секции protected объявляют методы Get/SetStream для непрямого доступа к приватному BaseClass.FStream со стороны наследников BaseClass, где бы то ни было объявленных


 
icWasya ©   (2005-06-30 15:26) [8]

unit Unit2;

interface

uses Classes;

type
TMyComp = class(TObject)  {áàçîâûé êëàññ}
 Private
   FStream : TStream;
 protected  
   procedure InitialStream(Var FStream : TStream);virtual; abstract;
   procedure WriteBuffer(Buffer : Pointer; Count : integer);
 public
   constructor Create;
   destructor Destroy;override;
 end;
end;

TMyFileStreamComp = class(TMyComp )
 protected
   procedure InitialStream(Var FStream : TStream);override;
end;

TMyMemoryStreamComp = class(TMyComp )
 protected
   procedure InitialStream(Var FStream : TStream);override;
end;

implementation

{ TMyComp }

constructor TMyComp.Create;
begin
 inherited;
 InitialStream(FStream);
end;

destructor TMyComp.Destroy;
begin
 FStream.Free;
 inherited;
end;

procedure TMyComp.WriteBuffer(Buffer : Pointer; Count : integer);
begin
 FStream.Write(Buffer,Count);
end;

{ TMyFileStreamComp }

procedure TMyFileStreamComp.InitialStream(Var FStream : TStream);
begin
AStream:=TFileStream.Create("file.txt",fmCreate);
end;

{ TMyMemoryStreamComp }

procedure TMyMemoryStreamComp.InitialStream(Var FStream : TStream);
begin
AStream:=TMemoryStream.Create;
end;

end.


 
Юрий Зотов ©   (2005-06-30 16:54) [9]

Реализуем базовый класс так:

type
 TMyBaseStreamClass = class
 private
   FStream: TStream;
 protected
   function CreateStream: TStream; virtual; abstract;
 public
   constructor Create;
   destructor Destroy; override;
   property Stream: TStream read FStream;
 end;

{ TMyBaseStreamClass }

constructor TMyBaseStreamClass.Create;
begin
 inherited;
 FStream := CreateStream
end;

destructor TMyBaseStreamClass.Destroy;
begin
 FStream.Free;
 inherited
end;

То есть, он отвечает только за автоматическое создание и уничтожение потока, а какой именно это будет поток - забота потомков (они должны перекрывать метод CreateStream, в нем вызывать конструктор конкретного класса потока и обеспечивать передачу ему параметров, если он их требует).

Кроме того, базовый класс выдает read-only свойство - ссылку на поток. Значит, прикладной код cможет свободно использовать родные свойства и методы потока - в том числе, ReadBuffer и WriteBuffer. И не нужны никакие собственные процедуры чтения-записи.

Потомков реализуем следующим образом.

Конструктор TMemoryStream параметров не требует, поэтому с ним все элементарно - просто замещаем CreateStream:

type
 TMyMemoryStreamClass = class(TMyBaseStreamClass)
 protected
   function CreateStream: TStream; override;
 end;

function TMyMemoryStreamClass.CreateStream: TStream;
begin
 Result := TMemoryStream.Create
end;

Конструктор TFileStream, наоборот, требует параметров, поэтому с ним получается чуть-чуть сложнее - но только чуть-чуть.

type
 TMyFileStreamClass = class(TMyBaseStreamClass)
 private
   FFileName: string;
   FMode: word;
 protected
   function CreateStream: TStream; override;
 public
   constructor Create(const FileName: string; Mode: word);
 end;

constructor TMyFileStreamClass.Create(const FileName: string; Mode: word);
begin
 FFileName := FileName;
 FMode := Mode;
 inherited Create
end;

function TMyFileStreamClass.CreateStream: TStream;
begin
 Result := TFileStream.Create(FFileName, FMode)
end;

Вот и все проблемы. По аналогии с показанными примерами можем легко плодить любых потомков базового класса.

Правда, все это, по сути, лишь повторяет функциональность той иерархии потов, которая уже есть в VCL - поэтому непонятно, зачем все это нужно. Разве что новая иерархия будет иерархией именно компонентских классов - тогда понять можно.


 
Другой Дмитрий   (2005-07-01 21:18) [10]

to Юрий Зотов
По моему тоже, что и я написал только вместо процедуры InitialStream - функция CreateStream или я чего-то не увидел (тогда шибко не ругайте)?

зачем все это нужно
Наследниками TMyComp будут не только различные компоненты со Stream"ами, но и например с TStrings. Это нужно для того, чтобы компонет TMyCompWriter смог записать информацию в любой компонент унаследованный от TMyComp (будь то какой-нибудь ListBox или TreeView или TFileStream) и записывать в них одни и тем-же методом, например WriteBuffer.



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

Форум: "Компоненты";
Текущий архив: 2006.01.01;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.155 c
4-1130329628
Хинт
2005-10-26 16:27
2006.01.01
Загрузить html страницу с сайта через WinAPI


4-1129750550
JJohn
2005-10-19 23:35
2006.01.01
процессы и потоки...


14-1133774290
REA
2005-12-05 12:18
2006.01.01
Семинар D2006


2-1134452961
Alex_C
2005-12-13 08:49
2006.01.01
Определение строчки в RichEdit


14-1134055758
VirEx
2005-12-08 18:29
2006.01.01
Delphi Eggs





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