答案 0 :(得分:9)
您必须为创建的子对象添加字段实例:
type
TRobot = class(TInterfacedObject, IStream)
private
FStream: TRobotStream;
function GetStream: IStream;
public
property Stream: IStream read GetStream implements IStream;
end;
destructor TRobot.Destroy;
begin
FStream.Free;
inherited;
end;
function TRobot.GetStream: IStream;
begin
if FStream = nil then
FStream := TRobotStream.Create(Self);
result := FStream;
end;
<强>更新强> 正如您已经猜到的那样,TRobotStream应该来自TAggregatedObject。声明应该是:
type
TRobotStream = class(TAggregatedObject, IStream)
...
end;
没有必要提及IUnknown。
在TRobot.GetStream中,行result := FStream
执行了一个隐含的FStream as IStream
,因此也不需要写出来。
FStream必须声明为TRobotStream而不是IStream,因此当TRobot实例被销毁时它可以被销毁。注意:TAggregatedObject没有引用计数,因此容器必须处理它的生命周期。
更新(Delphi 5代码):
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, activex, comobj;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
procedure LoadRobotFromDatabase(rs: IStream);
public
end;
type
TRobotStream = class(TAggregatedObject, IStream)
public
{ IStream }
function Seek(dlibMove: Largeint; dwOrigin: Longint;
out libNewPosition: Largeint): HResult; stdcall;
function SetSize(libNewSize: Largeint): HResult; stdcall;
function CopyTo(stm: IStream; cb: Largeint; out cbRead: Largeint; out cbWritten: Largeint): HResult; stdcall;
function Commit(grfCommitFlags: Longint): HResult; stdcall;
function Revert: HResult; stdcall;
function LockRegion(libOffset: Largeint; cb: Largeint; dwLockType: Longint): HResult; stdcall;
function UnlockRegion(libOffset: Largeint; cb: Largeint; dwLockType: Longint): HResult; stdcall;
function Stat(out statstg: TStatStg; grfStatFlag: Longint): HResult; stdcall;
function Clone(out stm: IStream): HResult; stdcall;
function Read(pv: Pointer; cb: Longint; pcbRead: PLongint): HResult; stdcall;
function Write(pv: Pointer; cb: Longint; pcbWritten: PLongint): HResult; stdcall;
end;
type
TRobot = class(TInterfacedObject, IStream)
private
FStream: TRobotStream;
function GetStream: IStream;
public
destructor Destroy; override;
property Stream: IStream read GetStream implements IStream;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
rs: IStream;
begin
rs := TRobot.Create;
LoadRobotFromDatabase(rs); //dummy method, just to demonstrate we use the stream
rs := nil;
end;
procedure TForm1.LoadRobotFromDatabase(rs: IStream);
begin
rs.Revert; //dummy method call, just to prove we can call it
end;
function TRobotStream.Clone(out stm: IStream): HResult;
begin
end;
function TRobotStream.Commit(grfCommitFlags: Integer): HResult;
begin
end;
function TRobotStream.CopyTo(stm: IStream; cb: Largeint; out cbRead, cbWritten: Largeint): HResult;
begin
end;
function TRobotStream.LockRegion(libOffset, cb: Largeint; dwLockType: Integer): HResult;
begin
end;
function TRobotStream.Read(pv: Pointer; cb: Integer; pcbRead: PLongint): HResult;
begin
end;
function TRobotStream.Revert: HResult;
begin
end;
function TRobotStream.Seek(dlibMove: Largeint; dwOrigin: Integer;
out libNewPosition: Largeint): HResult;
begin
end;
function TRobotStream.SetSize(libNewSize: Largeint): HResult;
begin
end;
function TRobotStream.Stat(out statstg: TStatStg; grfStatFlag: Integer): HResult;
begin
end;
function TRobotStream.UnlockRegion(libOffset, cb: Largeint; dwLockType: Integer): HResult;
begin
end;
function TRobotStream.Write(pv: Pointer; cb: Integer; pcbWritten: PLongint): HResult;
begin
end;
destructor TRobot.Destroy;
begin
FStream.Free;
inherited;
end;
function TRobot.GetStream: IStream;
begin
if FStream = nil then
FStream := TRobotStream.Create(Self);
result := FStream;
end;
end.
enter code here
答案 1 :(得分:3)
您的类不需要委派从任何特定类继承。如果已经实现了适当的方法,您可以从TObject继承。我将保持简单,并使用TInterfacedObject进行说明,它提供了您已经识别的3种核心方法。
此外,您不应该需要TRobotStream = class(TAggregatedObject, IUnknown, IStream)
。您可以简单地声明IStream继承自IUnknown。顺便说一句,我总是给我的接口一个GUID(按下组合Ctrl + Shift + G)。
根据您的特定需求,可以应用多种不同的方法和技术。
最简单的委托是通过接口。
TRobotStream = class(TinterfacedObject, IStream)
TRobot = class(TInterfacedObject, IStream)
private
//The delegator delegates the implementations of IStream to the child object.
//Ensure the child object is created at an appropriate time before it is used.
FRobotStream: IStream;
property RobotStream: IStream read FRobotStream implements IStream;
end;
或许有一点需要注意: