由于DELPHI不允许unit单元的循环引用,而类的成员在定义时,必须要用interface里的类型,因此要实现类成员的互相引用,必须用变通的方法.
unit1
interface
uses
, unit2 , ;
type
tA = class
private
bbb : tB;
end;
interface
uses
, unit2 , ;
type
tA = class
private
bbb : tB;
end;
unit2
interface
uses
, unit1 , ;
type
tB = class
private
aaa : tA;
end;
interface
uses
, unit1 , ;
type
tB = class
private
aaa : tA;
end;
上面的2个unit不能通过编译,因为循环引用了.如果不循环引用,又出现类型没定义。反正就是不能通过编译。
有人说尽量避免类的这种互相定义,实在要定义时就把这2个类放在一个unit中。但是这样并不符合我们的设想。
在什么情况下需要这种互相定义呢,我们假设一个老师只有1个学生,一个学生只有1个老师,那么一个学生,那他就有老师,因此他有一个成员变量,指向他的老师的。而这个老师也会有1个成员变量指向他的学生。这时就发生了嵌套定义。
由于unit不能循环引用的限制,实现这种嵌套好像只能放到一个unit中了,但是我们有不在一个unit的需要。那要如何实现呢。
我们知道在implementation中uses的unit不会发生循环引用,而类的实现部分(定义部分是在interface)恰好是在implementation,在implementation里uses的类型可以在implementation范围内引用。因此我们是可以在类方法的实现部分使用到另外一个类。但是在类的方法中定义的变量是局部的,一退出过程就消失了,不能随时引用。
我们知道对象实质是一个dword型的指针.只要我们传递另外一个类的指针保存起来,在要调用另外一个类的方法时再强制转换后使用。
具体测试在下面的2个unit中
unit Unit1;
interface
uses
Windows , Messages , SysUtils , Variants , Classes , Graphics , Controls , Forms ,
Dialogs , StdCtrls;
type
TA = class
private
{ Private declarations }
// tb : pinteger;
public
classB : pdword;
procedure setTB(p : pinteger);
procedure doTest;
end;
TForm1 = class(TForm)
Button1 : TButton;
procedure Button1Click(Sender : TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1 : TForm1;
implementation
uses
unit2;
{ $R *. dfm}
var
aa : tA;
bb : tB;
procedure TForm1 . Button1Click(Sender : TObject);
var
b : tB;
begin
aa := tA . Create;
bb := tb . Create;
aa . classB := @bb ;
bb . classA := @aa ;
b := tB(aa . classB);
b . doTest;
end;
{ TA }
procedure TA . doTest;
begin
showmessage( ' AAA ' );
end;
end .
interface
uses
Windows , Messages , SysUtils , Variants , Classes , Graphics , Controls , Forms ,
Dialogs , StdCtrls;
type
TA = class
private
{ Private declarations }
// tb : pinteger;
public
classB : pdword;
procedure setTB(p : pinteger);
procedure doTest;
end;
TForm1 = class(TForm)
Button1 : TButton;
procedure Button1Click(Sender : TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1 : TForm1;
implementation
uses
unit2;
{ $R *. dfm}
var
aa : tA;
bb : tB;
procedure TForm1 . Button1Click(Sender : TObject);
var
b : tB;
begin
aa := tA . Create;
bb := tb . Create;
aa . classB := @bb ;
bb . classA := @aa ;
b := tB(aa . classB);
b . doTest;
end;
{ TA }
procedure TA . doTest;
begin
showmessage( ' AAA ' );
end;
end .
unit Unit2;
interface
uses
Windows , Messages , SysUtils , Variants , Classes , Graphics , Controls , Forms ,
Dialogs , StdCtrls;
type
tB = class
private
{ Private declarations }
// ta : pinteger;
public
classA : pdword;
procedure doTest;
end;
implementation
uses
unit1;
{ tB }
procedure tB . doTest;
begin
showmessage( ' BBB ' );
end;
end .
interface
uses
Windows , Messages , SysUtils , Variants , Classes , Graphics , Controls , Forms ,
Dialogs , StdCtrls;
type
tB = class
private
{ Private declarations }
// ta : pinteger;
public
classA : pdword;
procedure doTest;
end;
implementation
uses
unit1;
{ tB }
procedure tB . doTest;
begin
showmessage( ' BBB ' );
end;
end .