用一个简单的例子可以最好地显示,问题是底部的ShowMessage:
type
TFrmSelfRef = class(TForm)
BtnTest: TButton;
procedure BtnTestClick(Sender: TObject);
private
public
procedure ExternalCaller;
end;
type
TProcType = procedure of Object;
type
TSomeObj = class
private
FIdentifier: Integer;
FCaller : TProcType;
public
property Caller : TProcType read FCaller write FCaller;
property Identifier : integer read FIdentifier write FIdentifier;
end;
[snip]
procedure TFrmSelfRef.BtnTestClick(Sender: TObject);
var
lSomeObj: TSomeObj;
begin
lSomeObj := TSomeObj.Create;
lSomeObj.Identifier := 200;
lSomeObj.Caller := ExternalCaller;
lSomeObj.Caller;
lSomeObj.Free;
end;
procedure TFrmSelfRef.ExternalCaller;
begin
ShowMessage('Can I access lSomeObj.Identifier (value:200) here?');
end;
原因:我已经有一个TSomeObj实例,其中包含Caller所需的所有信息,但是ExternalCaller引用了我不想链接(包含TSomeObj的其他对象/单元)。
答案 0 :(得分:4)
Peter's comment显示了一种可能性。它需要一些转发技巧:
type
TSomeObj = class;
TFrmSelfRef = class(TForm)
BtnTest: TButton;
procedure BtnTestClick(Sender: TObject);
private
public
procedure ExternalCaller(ASomeObj: TSomeObj);
end;
TProcType = procedure(Sender: TSomeObj) of Object;
TSomeObj = class
private
FIdentifier: Integer;
FCaller : TProcType;
public
property Caller : TProcType read FCaller write FCaller;
property Identifier : integer read FIdentifier write FIdentifier;
end;
[snip]
procedure TFrmSelfRef.BtnTestClick(Sender: TObject);
var
lSomeObj: TSomeObj;
begin
lSomeObj := TSomeObj.Create;
lSomeObj.Identifier := 200;
lSomeObj.Caller := ExternalCaller;
lSomeObj.Caller(lSomeObj);
end;
procedure TFrmSelfRef.ExternalCaller(ASomeObj: TSomeObj);
begin
ShowMessage('I can access TSomeObj here! Identifier property value: ' + IntToStr(ASomeObj.Identifier));
end;
答案 1 :(得分:3)
不,那不可能。
尽管ExternalCaller
是一个方法-TProcType
是一个方法类型(“对象”),但{{ 1}}是指创建Self
的{{1}}对象;它不引用ExternalCaller()
。
此外,您可能已经知道这一点,但是从不写
TFrmSelfRef
相反,写
lSomeObj
如果发生异常(或者您通过使用lSomeObj
或lSomeObj := TSomeObj.Create;
lSomeObj.Identifier := 200;
lSomeObj.Caller := ExternalCaller;
lSomeObj.Caller;
lSomeObj.Free;
或lSomeObj := TSomeObj.Create;
try
lSomeObj.Identifier := 200;
lSomeObj.Caller := ExternalCaller;
lSomeObj.Caller;
finally
lSomeObj.Free;
end;
离开)-就像在Delphi中一样-一定不要泄漏内存和其他资源! 始终使用Exit
保护资源。
答案 2 :(得分:1)
您要的是可能并且带有一些丑陋的TMethod
黑客,例如:
type
TFrmSelfRef = class(TForm)
BtnTest: TButton;
procedure BtnTestClick(Sender: TObject);
private
public
procedure ExternalCaller;
end;
type
TProcType = procedure of object;
type
TSomeObj = class
private
FIdentifier: Integer;
FCaller : TProcType;
public
property Caller : TProcType read FCaller write FCaller;
property Identifier : Integer read FIdentifier write FIdentifier;
end;
...
procedure TFrmSelfRef.BtnTestClick(Sender: TObject);
var
lSomeObj: TSomeObj;
P: TProcType;
begin
lSomeObj := TSomeObj.Create;
try
lSomeObj.Identifier := 200;
//lSomeObj.Caller := ExternalCaller;
P := ExternalCaller;
TMethod(P).Data := lSomeObj;
lSomeObj.Caller := P;
lSomeObj.Caller;
finally
lSomeObj.Free;
end;
end;
procedure TFrmSelfRef.ExternalCaller;
begin
ShowMessage('The Identifier is ' + IntToStr(TSomeObj(Self).Identifier));
end;
但是,如果滥用,这将非常危险。我不推荐这种方法!我只是出于完整性考虑而提出。
改为使用彼得的解决方案。
另一种解决方案是将ExternalCaller()
移至TSomeObj
,例如:
type
TFrmSelfRef = class(TForm)
BtnTest: TButton;
procedure BtnTestClick(Sender: TObject);
private
public
end;
type
TProcType = procedure of object;
type
TSomeObj = class
private
FIdentifier: Integer;
FCaller : TProcType;
public
procedure ExternalCaller;
property Caller : TProcType read FCaller write FCaller;
property Identifier : Integer read FIdentifier write FIdentifier;
end;
...
procedure TFrmSelfRef.BtnTestClick(Sender: TObject);
var
lSomeObj: TSomeObj;
P: TProcType;
begin
lSomeObj := TSomeObj.Create;
try
lSomeObj.Identifier := 200;
lSomeObj.Caller := lSomeObj.ExternalCaller;
lSomeObj.Caller;
finally
lSomeObj.Free;
end;
end;
procedure TSomeObj.ExternalCaller;
begin
ShowMessage('The Identifier is ' + IntToStr(Identifier));
end;