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

Вниз

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

 
Другой Дмитрий   (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;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.036 c
2-1134150434
bg8
2005-12-09 20:47
2006.01.01
Опять serial порт...


1-1133699191
Vetaly
2005-12-04 15:26
2006.01.01
Пропуск строк кода компилятором


14-1133889193
Kerk
2005-12-06 20:13
2006.01.01
Самый слабый по составу чемпионат мира в истории


2-1134659544
kalim
2005-12-15 18:12
2006.01.01
Ado connection


1-1133789961
Экспериментатор
2005-12-05 16:39
2006.01.01
Как в MDI приложении сделать чтобы MDI-child окно максимизировало