D5DG中的Form Wizard就是很好的一例。unit ABWizard;interfaceuses Windows, Classes, ToolsAPI;type TAppBarWizard = class(TNotifierObject, IOTAWizard, IOTARepositoryWizard, IOTAFormWizard, IOTACreator, IOTAModuleCreator) private FUnitIdent: string; FClassName: string; FFileName: string; protected // IOTAWizard methods function GetIDString: string; function GetName: string; function GetState: TWizardState; procedure Execute; // IOTARepositoryWizard / IOTAFormWizard methods function GetAuthor: string; function GetComment: string; function GetPage: string; function GetGlyph: Cardinal; // IOTACreator methods function GetCreatorType: string; function GetExisting: Boolean; function GetFileSystem: string; function GetOwner: IOTAModule; function GetUnnamed: Boolean; // IOTAModuleCreator methods function GetAncestorName: string; function GetImplFileName: string; function GetIntfFileName: string; function GetFormName: string; function GetMainForm: Boolean; function GetShowForm: Boolean; function GetShowSource: Boolean; function NewFormFile(const FormIdent, AncestorIdent: string): IOTAFile; function NewImplSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile; function NewIntfSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile; procedure FormCreated(const FormEditor: IOTAFormEditor); end;implementationuses Forms, AppBars, SysUtils, DesignIntf;{$R CodeGen.res}type TBaseFile = class(TInterfacedObject) private FModuleName: string; FFormName: string; FAncestorName: string; public constructor Create(const ModuleName, FormName, AncestorName: string); end; TUnitFile = class(TBaseFile, IOTAFile) protected function GetSource: string; function GetAge: TDateTime; end; TFormFile = class(TBaseFile, IOTAFile) protected function GetSource: string; function GetAge: TDateTime; end;{ TBaseFile }constructor TBaseFile.Create(const ModuleName, FormName, AncestorName: string); begin inherited Create; FModuleName := ModuleName; FFormName := FormName; FAncestorName := AncestorName; end;{ TUnitFile }function TUnitFile.GetSource: string; var Text: string; ResInstance: THandle; HRes: HRSRC; begin ResInstance := FindResourceHInstance(HInstance); HRes := FindResource(ResInstance, 'CODEGEN', RT_RCDATA); Text := PChar(LockResource(LoadResource(ResInstance, HRes))); SetLength(Text, SizeOfResource(ResInstance, HRes)); Result := Format(Text, [FModuleName, FFormName, FAncestorName]); end;function TUnitFile.GetAge: TDateTime; begin Result := -1; end;{ TFormFile }function TFormFile.GetSource: string; const FormText = 'object %0:s: T%0:s'#13#10'end'; begin Result := Format(FormText, [FFormName]); end;function TFormFile.GetAge: TDateTime; begin Result := -1; end;{ TAppBarWizard }{ TAppBarWizard.IOTAWizard }function TAppBarWizard.GetIDString: string; begin Result := 'DDG.AppBarWizard'; end;function TAppBarWizard.GetName: string; begin Result := 'DDG AppBar Wizard'; end;function TAppBarWizard.GetState: TWizardState; begin Result := [wsEnabled]; end;procedure TAppBarWizard.Execute; begin (BorlandIDEServices as IOTAModuleServices).GetNewModuleAndClassName( 'AppBar', FUnitIdent, FClassName, FFileName); (BorlandIDEServices as IOTAModuleServices).CreateModule(Self); end;{ TAppBarWizard.IOTARepositoryWizard / TAppBarWizard.IOTAFormWizard }function TAppBarWizard.GetGlyph: Cardinal; begin Result := 0; // use standard icon end;function TAppBarWizard.GetPage: string; begin Result := 'DDG'; end;function TAppBarWizard.GetAuthor: string; begin Result := 'Delphi Developer''s Guide'; end;function TAppBarWizard.GetComment: string; begin Result := 'Creates a new AppBar form.' end;{ TAppBarWizard.IOTACreator }function TAppBarWizard.GetCreatorType: string; begin Result := ''; end;function TAppBarWizard.GetExisting: Boolean; begin Result := False; end;function TAppBarWizard.GetFileSystem: string; begin Result := ''; end;function TAppBarWizard.GetOwner: IOTAModule; var I: Integer; ModServ: IOTAModuleServices; Module: IOTAModule; ProjGrp: IOTAProjectGroup; begin Result := nil; ModServ := BorlandIDEServices as IOTAModuleServices; for I := 0 to ModServ.ModuleCount - 1 do begin Module := ModSErv.Modules[I]; // find current project group if CompareText(ExtractFileExt(Module.FileName), '.bpg') = 0 then if Module.QueryInterface(IOTAProjectGroup, ProjGrp) = S_OK then begin // return active project of group Result := ProjGrp.GetActiveProject; Exit; end; end; end;function TAppBarWizard.GetUnnamed: Boolean; begin Result := True; end;{ TAppBarWizard.IOTAModuleCreator }function TAppBarWizard.GetAncestorName: string; begin Result := 'TAppBar'; end;function TAppBarWizard.GetImplFileName: string; var CurrDir: array[0..MAX_PATH] of char; begin // Note: full path name required! GetCurrentDirectory(SizeOf(CurrDir), CurrDir); Result := Format('%s\%s.pas', [CurrDir, FUnitIdent, '.pas']); end;function TAppBarWizard.GetIntfFileName: string; begin Result := ''; end;function TAppBarWizard.GetFormName: string; begin Result := FClassName; end;function TAppBarWizard.GetMainForm: Boolean; begin Result := False; end;function TAppBarWizard.GetShowForm: Boolean; begin Result := True; end;function TAppBarWizard.GetShowSource: Boolean; begin Result := True; end;function TAppBarWizard.NewFormFile(const FormIdent, AncestorIdent: string): IOTAFile; begin Result := TFormFile.Create('', FormIdent, AncestorIdent); end;function TAppBarWizard.NewImplSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile; begin Result := TUnitFile.Create(ModuleIdent, FormIdent, AncestorIdent); end;function TAppBarWizard.NewIntfSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile; begin Result := nil; end;procedure TAppBarWizard.FormCreated(const FormEditor: IOTAFormEditor); begin // do nothing end;end.
上述例子中可以如此: var a: IOTARepositoryWizard; b: IOTACreator; c: TAppBarWizard; c := TAppBarWizard.Create; b := c; a := c; // a = b as IOTARepositoryWizard; ...
在这方面,Java,C#和Delphi具有同样的特性。
TAppBarWizard = class(TNotifierObject, IOTAWizard, IOTARepositoryWizard,
IOTAFormWizard, IOTACreator, IOTAModuleCreator)
private
FUnitIdent: string;
FClassName: string;
FFileName: string;
protected
// IOTAWizard methods
function GetIDString: string;
function GetName: string;
function GetState: TWizardState;
procedure Execute;
// IOTARepositoryWizard / IOTAFormWizard methods
function GetAuthor: string;
function GetComment: string;
function GetPage: string;
function GetGlyph: Cardinal;
// IOTACreator methods
function GetCreatorType: string;
function GetExisting: Boolean;
function GetFileSystem: string;
function GetOwner: IOTAModule;
function GetUnnamed: Boolean;
// IOTAModuleCreator methods
function GetAncestorName: string;
function GetImplFileName: string;
function GetIntfFileName: string;
function GetFormName: string;
function GetMainForm: Boolean;
function GetShowForm: Boolean;
function GetShowSource: Boolean;
function NewFormFile(const FormIdent, AncestorIdent: string): IOTAFile;
function NewImplSource(const ModuleIdent, FormIdent,
AncestorIdent: string): IOTAFile;
function NewIntfSource(const ModuleIdent, FormIdent,
AncestorIdent: string): IOTAFile;
procedure FormCreated(const FormEditor: IOTAFormEditor);
end;implementationuses Forms, AppBars, SysUtils, DesignIntf;{$R CodeGen.res}type
TBaseFile = class(TInterfacedObject)
private
FModuleName: string;
FFormName: string;
FAncestorName: string;
public
constructor Create(const ModuleName, FormName, AncestorName: string);
end; TUnitFile = class(TBaseFile, IOTAFile)
protected
function GetSource: string;
function GetAge: TDateTime;
end; TFormFile = class(TBaseFile, IOTAFile)
protected
function GetSource: string;
function GetAge: TDateTime;
end;{ TBaseFile }constructor TBaseFile.Create(const ModuleName, FormName,
AncestorName: string);
begin
inherited Create;
FModuleName := ModuleName;
FFormName := FormName;
FAncestorName := AncestorName;
end;{ TUnitFile }function TUnitFile.GetSource: string;
var
Text: string;
ResInstance: THandle;
HRes: HRSRC;
begin
ResInstance := FindResourceHInstance(HInstance);
HRes := FindResource(ResInstance, 'CODEGEN', RT_RCDATA);
Text := PChar(LockResource(LoadResource(ResInstance, HRes)));
SetLength(Text, SizeOfResource(ResInstance, HRes));
Result := Format(Text, [FModuleName, FFormName, FAncestorName]);
end;function TUnitFile.GetAge: TDateTime;
begin
Result := -1;
end;{ TFormFile }function TFormFile.GetSource: string;
const
FormText =
'object %0:s: T%0:s'#13#10'end';
begin
Result := Format(FormText, [FFormName]);
end;function TFormFile.GetAge: TDateTime;
begin
Result := -1;
end;{ TAppBarWizard }{ TAppBarWizard.IOTAWizard }function TAppBarWizard.GetIDString: string;
begin
Result := 'DDG.AppBarWizard';
end;function TAppBarWizard.GetName: string;
begin
Result := 'DDG AppBar Wizard';
end;function TAppBarWizard.GetState: TWizardState;
begin
Result := [wsEnabled];
end;procedure TAppBarWizard.Execute;
begin
(BorlandIDEServices as IOTAModuleServices).GetNewModuleAndClassName(
'AppBar', FUnitIdent, FClassName, FFileName);
(BorlandIDEServices as IOTAModuleServices).CreateModule(Self);
end;{ TAppBarWizard.IOTARepositoryWizard / TAppBarWizard.IOTAFormWizard }function TAppBarWizard.GetGlyph: Cardinal;
begin
Result := 0; // use standard icon
end;function TAppBarWizard.GetPage: string;
begin
Result := 'DDG';
end;function TAppBarWizard.GetAuthor: string;
begin
Result := 'Delphi Developer''s Guide';
end;function TAppBarWizard.GetComment: string;
begin
Result := 'Creates a new AppBar form.'
end;{ TAppBarWizard.IOTACreator }function TAppBarWizard.GetCreatorType: string;
begin
Result := '';
end;function TAppBarWizard.GetExisting: Boolean;
begin
Result := False;
end;function TAppBarWizard.GetFileSystem: string;
begin
Result := '';
end;function TAppBarWizard.GetOwner: IOTAModule;
var
I: Integer;
ModServ: IOTAModuleServices;
Module: IOTAModule;
ProjGrp: IOTAProjectGroup;
begin
Result := nil;
ModServ := BorlandIDEServices as IOTAModuleServices;
for I := 0 to ModServ.ModuleCount - 1 do
begin
Module := ModSErv.Modules[I];
// find current project group
if CompareText(ExtractFileExt(Module.FileName), '.bpg') = 0 then
if Module.QueryInterface(IOTAProjectGroup, ProjGrp) = S_OK then
begin
// return active project of group
Result := ProjGrp.GetActiveProject;
Exit;
end;
end;
end;function TAppBarWizard.GetUnnamed: Boolean;
begin
Result := True;
end;{ TAppBarWizard.IOTAModuleCreator }function TAppBarWizard.GetAncestorName: string;
begin
Result := 'TAppBar';
end;function TAppBarWizard.GetImplFileName: string;
var
CurrDir: array[0..MAX_PATH] of char;
begin
// Note: full path name required!
GetCurrentDirectory(SizeOf(CurrDir), CurrDir);
Result := Format('%s\%s.pas', [CurrDir, FUnitIdent, '.pas']);
end;function TAppBarWizard.GetIntfFileName: string;
begin
Result := '';
end;function TAppBarWizard.GetFormName: string;
begin
Result := FClassName;
end;function TAppBarWizard.GetMainForm: Boolean;
begin
Result := False;
end;function TAppBarWizard.GetShowForm: Boolean;
begin
Result := True;
end;function TAppBarWizard.GetShowSource: Boolean;
begin
Result := True;
end;function TAppBarWizard.NewFormFile(const FormIdent,
AncestorIdent: string): IOTAFile;
begin
Result := TFormFile.Create('', FormIdent, AncestorIdent);
end;function TAppBarWizard.NewImplSource(const ModuleIdent, FormIdent,
AncestorIdent: string): IOTAFile;
begin
Result := TUnitFile.Create(ModuleIdent, FormIdent, AncestorIdent);
end;function TAppBarWizard.NewIntfSource(const ModuleIdent, FormIdent,
AncestorIdent: string): IOTAFile;
begin
Result := nil;
end;procedure TAppBarWizard.FormCreated(const FormEditor: IOTAFormEditor);
begin
// do nothing
end;end.
你给我的例子过于复杂;我不知道通过接口类TAppBarWizard,
得到了那些方法???
var
a: IOTARepositoryWizard;
b: IOTACreator;
c: TAppBarWizard; c := TAppBarWizard.Create;
b := c;
a := c;
// a = b as IOTARepositoryWizard;
...
我对接口的理解是:接口定义了一些方法(但没有实现)。
继承一个接口的类必须实现接口中定义的方法。
可以说你继承一个接口什么都没得到,还要实现接口定义的方法。
现在我的理解也是这样的,实现在本类中,那这样的话,接口有什么用!
哪里可以找到关于“聚合”的资料!
type
TAncestorA = class(TInterfacedObject, IAncestorA)
protected
procedure IAncestorAFunc; //声明在IAncestorA中的方法,这里提供实现
……
end; TAncestorB = class(TIntefacedObject, IAncestorB)
protected
procedure IAncestorBFunc; //声明在IAncestorB中的方法,这里提供实现
……
end; TMyClass = class(TInterfacedObject, IAncestorA, IAncestorB)
private
AncestorAObj: IAncestorA;
AncestorBObj: IAncestorB;
public
constructor Create; override;
destructor Destroy; override;
procedure IAncestorAFunc;
procedure IAncestorBFunc;
end;Implementconstructor TMyClass.Create;
begin
inherited;
AncestorAObj := CreateComObj(……); //创建TAncestorA的实例
AncestorBObj := CreateComObj(……); //创建TAncestorB的实例
end;destructor TMyClass.Destroy;
begin
AncestorAObj := nil;
AncestorBObj := nil;
inherited;
end;procedure TMyClass.IAncestorAFunc;
begin
AncestorAObj.IAncestorAFunc;
end;procedure TMyClass.IAncestorBFunc;
begin
AncestorBObj.IAncestorBFunc;
end;
IWalker = interface
['{6783F83D-A00C-4A25-B3D6-337A42038974}']
function Work: string;
function Run: string;
function GetPos: integer;
procedure SetPos(Value: integer);
property Position: integer read GetPos write SetPos;
end; IJumper = interface
['{414BEF73-7543-4A15-81DC-F8BB91019AFC}']
function Jump: string;
function walk: string;
function GetPos: integer;
procedure SetPos(Value: integer);
property Position: integer read GetPos write SetPos;
end;
TJumpImpl = class(TInterfacedObject, IJumper)
end;TAthlete = class(TInterfacedObject, IWalker, IJumper)
private
fJumpImpl: TJumpImpl;
public
constructor Create;
function Run: string; virtual;
function Walk1: string; virtual;
function IWalker.Walk = Walk1;
function GetPos: integer;
procedure SetPos(Value: integer);
property Jumper: TJumpImpl read fJumpImpl implements IJumper;
end;constructor TAthlete.Create;
begin
fJumpImpl := TJumpImpl.Create;
end;这样,就实现了多继承
有时候IA、IB的功能会超过了你需要的功能,比如IAncestorFunc9根本不是TMyClass中应该具有的功能,如果将这个方法体现在TMyClass中,反而会引起TMyClass概念模糊,职责不清。这时用聚合的方式可以很容易的对成员的功能进行裁减。
或者对于TMyClass的使用者来说,需要更加明确的功能定义。比如IA提供了CopyFileTo,DeleteFile,IB提供了CopyDir,DeleteDir,而TMyClass作为一个文件管理器,可能需要提供Copy、Delete、Cut功能,用聚合的优点就更加体现出来了。