Hola, roman,
(6) I meant that I could forget about something
(5)
Mix-in classes is particular case of the multiple ihneritance.
When you don't want to use interface references,
and don't need the automatic life time management,
but want to add to your classes some different
orthogonal functionalities.
Mix-in interfaces allow make the interface of the base class compact.
Código Delphi
[-]
type
TMixInBase = class(TPersistent, IUnknown)
public
function TInterfacedObject.QueryInterface(const IID: TGUID; out Obj): HResult;
function TInterfacedObject._AddRef: Integer;
function TInterfacedObject._Release: Integer;
end;
TSomeBaseObject = class(TMixInBase)
end;
IName = interface
['{D1693279-7EEA-417B-BCFC-BD7DC29E2763}']
function GetName: string;
procedure SetName(const AName: string);
end;
ICloneable = interface
['{8990AA78-364E-4BFA-B444-CF12608D39FF}']
function Clone: TSomeBaseObject;
end;
IStreamable = interface
['{3B83C00D-85E0-4CDC-B757-549592C756FA}']
procedure SaveData(Dest: TStream);
procedure LoadData(Src: TStream);
end;
TChildProc = procedure(Child: TSomeBaseObject) of object;
IComposite = interface
['{07CB94B4-231F-41FF-B51E-1570D69966C5}']
procedure GetChildren(Proc: TChildProc);
end;
IHitTest = interface
['{4279B456-5749-44CB-BCBF-B2FFEF0CCB15}']
function HitTest(const Point: TPoint): Boolean;
end;
TSomeDescendant = class(TSomeBaseObject, IName, ICloneable, IStreamable)
end;
TOtherDescendant = class(TSomeBaseObject, IComposite, IStreamable)
end;
function GetName(Obj: TSomeBaseObject): string;
var intf: IName;
begin
if Obj.GetInterface(IName, intf)
then Result := intf.GetName
else Result := '';
end;
function Clone(Obj: TSomeBaseObject): TSomeBaseObject;
var intf: ICloneable;
begin
if Obj.GetInterface(ICloneable, intf)
then Result := intf.Clone
else raise Exception.Create('Object does''nt support ICloneable');
end;