I got two classes (in my example TObject1 and TObject2) which know each other via interfaces (IObject1, IObject2). As you probably know in Delphi this will lead to a memory
It looks like you want both objects to share their reference count. You could do that by letting a third object (TPair
) handle the reference counting. A nice way to accomplish this is by using the implements
keyword. You can choose to keep this third object hidden, or to interact with that as well.
With the code below you can either create a TPairChildA
, a TPairChildB
or their 'parent' TPair
. Any of them will create the others when needed and all created objects will be kept alive until none are referenced anymore. You can of course add interfaces like your IObject1
to the objects, but I kept them out for simplicity.
unit ObjectPair;
interface
type
TPairChildA = class;
TPairChildB = class;
TPair = class( TInterfacedObject )
protected
FChildA : TPairChildA;
FChildB : TPairChildB;
function GetChildA : TPairChildA;
function GetChildB : TPairChildB;
public
destructor Destroy; override;
property ChildA : TPairChildA read GetChildA;
property ChildB : TPairChildB read GetChildB;
end;
TPairChild = class( TObject , IInterface )
protected
FPair : TPair;
property Pair : TPair read FPair implements IInterface;
public
constructor Create( APair : TPair = nil ); virtual;
end;
TPairChildA = class( TPairChild )
protected
function GetSibling : TPairChildB;
public
constructor Create( APair : TPair = nil ); override;
property Sibling : TPairChildB read GetSibling;
end;
TPairChildB = class( TPairChild )
protected
function GetSibling : TPairChildA;
public
constructor Create( APair : TPair = nil ); override;
property Sibling : TPairChildA read GetSibling;
end;
implementation
//==============================================================================
// TPair
destructor TPair.Destroy;
begin
FChildA.Free;
FChildB.Free;
inherited;
end;
function TPair.GetChildA : TPairChildA;
begin
if FChildA = nil then
FChildA := TPairChildA.Create( Self );
Result := FChildA;
end;
function TPair.GetChildB : TPairChildB;
begin
if FChildB = nil then
FChildB := TPairChildB.Create( Self );
Result := FChildB;
end;
// END TPair
//==============================================================================
// TPairChild
constructor TPairChild.Create( APair : TPair = nil );
begin
if APair = nil then
FPair := TPair.Create
else
FPair := APair;
end;
// END TPairChild
//==============================================================================
// TPairChildA
constructor TPairChildA.Create( APair : TPair = nil );
begin
inherited;
FPair.FChildA := Self;
end;
function TPairChildA.GetSibling : TPairChildB;
begin
Result := FPair.ChildB;
end;
// END TPairChildA
//==============================================================================
// TPairChildB
constructor TPairChildB.Create( APair : TPair = nil );
begin
inherited;
FPair.FChildB := Self;
end;
function TPairChildB.GetSibling : TPairChildA;
begin
Result := FPair.ChildA;
end;
// END TPairChildB
//==============================================================================
end.
A usage example:
procedure TForm1.Button1Click( Sender : TObject );
var
objA : TPairChildA;
ifA , ifB : IInterface;
begin
objA := TPairChildA.Create;
ifA := objA;
ifB := objA.Sibling;
ifA := nil;
ifB := nil; // This frees all three objects.
end;