关于Self
所有的类都有一个隐含的字段叫Self,在内存中Self是一个指向类实例的指针。
首先我们来看看,如果Self不是隐含字段的话,那么TMyRec类到底是一个什么样子:
TMyRect = class private Self: TMyRect; { Self隐含字段} Left: Integer; Top: Integer; Right: Integer; Bottom: Integer; Text: PChar; public function GetWidth: Integer; function GetHeight: Integer; procedure SetRect(ALeft, ATop, ARight, ABottom: Integer); constructor Create; constructor CreateVal(ALeft, ATop, ARight, ABottom: Integer); destructor Destroy; override; end;
对于编译器来说,这就是实际TMyRect类的样子。当类对象建立时,Self指针会自动初始化为内存中类的地址:
Rect1 := TMyRect.CreateVal(100, 100, 500, 500); { 现在Rect1和Rect1.Self具有相同的值,因为两者都包含对象在内存中的地址}
Self到底是什么意思?
记住每个类实例都会得到各自的类字段拷贝,但所有类实例享有类的相同方法集(没有必要为每个实例都复制代码),这样编译器怎么识别哪个实例调用哪个方法呢?所有类方法都有一个隐含Self参数,为了声明这一点,假设有一个TMyRect类的函数叫GetWidth,其表现如下:
function TMyRect.GetWidth: Integer; begin Result := Right - Left; end;
对大家来说,这个就是这个样子的,但是对于编译器来说,其表现形式应如下:
function TMyRect.GetWidth: Integer; begin Result := Self.Right - Self.Left; end;
看来Self是在幕后工作的,我们不必担心其是怎样发生的只要只奥它发生了就行。
Caution
绝不要修改Self指针,可以用它把一个指向类的指针传送给其他方法,或者作为构造其他类的参数,但不要改变它的值,要学会把Self当作一个只读变量。
Note
前面讨论过类方法(class method)不能存取类字段,这正是因为类方法没有一个隐含的Self参数,而普通的方法可以存取类字段。如果没有Self,普通方法就不能存取类字段。
现在还不要太担心怎样使用Self,当开始使用VCL时,就需要在Delphi应用程序中用Self,这样很快就会明白它的用法。