Форум: "Компоненты";
Текущий архив: 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.009 c