类(class)、类的类(class of class)、类变量(class variable) 的关系
到类(class) 就是 VMTptr。在 Delphi 中还可以用 class of 关键字定义类的类,并且可以使用类的类定义类变量。从语法上理解这三者的关键并不难,把类当成普通的数据类型来考虑就可以了。在编译器级别上表现如何呢?
为了简化讨论,我们使用 TObject、TClass 和 TMyClass 来代表上面说的三种类型:
type
TClass = class of TObject;
var
TMyClass: TClass;
MyObject: TObject;
begin
TMyClass := TObject;
MyObject := TObject.Create;
MyObject := TClass.Create;
MyObject := TMyClass.Create;
end;
在上面的例子中,三个 TObject 对象都被成功地创建了。编译器的实现是:TObject 是一个 VMTPtr 常量。TClass 也是一个 VMTptr 常量,它的值就是 TObject。TMyClass 是一个 VMTptr 变量,它被赋值为 TObject。TObject.Create 与 TClass.Create 的汇编代码完全相同。但 TClass 不仅缺省代表一个类,而且还(主要)代表了类的类型,可以用它来定义类变量,实现一些类级别的操作。
举例:
TMyControlClass = class of TMyControl , 不是子代,后代。
TMyControl2=class(TMyControl) 这个 TMycontrol2 才是 TMyControl 的子代,后代。
function CreateMyControl(AControlClass:TControlClass);
改成
function CreateMyControl(AControlClass:TControl);
请注意,在这里,把 TControlClass 改为 TControl,意思就完全变了!
第一个 AControlClass:TControlClass 表示这里要传入一个类别!
第二个,(AControlClass:TControl); 表示这里要传入一个变数(一个 var)这个变数的类型是 TControl。
完全是两个不同的意思!
通常的变数,假设你有3个TButton,Button1, Button2, Button2,你要修改 Button 上的 Caption:
procedure ChangeCaption(AButton: TButton);
begin
if AButton = Button1 then AButton.Caption := 'abc' else if AButton = Button2 then AButton.Caption := '123';
end;
你可以把你的 Button1 当作变数送进这个 procedure 里去:
ChangeCaption(Button1); <---- 这里送进去一个 TButton 类型的变数!
---------------
现在,更进一步:
procedure ChangeCaption(AButton: TControl);
begin
if AButton = Button1 then AButton.Caption := 'abc' else if AButton = Button2 then AButton.Caption := '123'
else if AButton is TEdit then TEdit(AButton).Text := 'this is a Edit';
end;
你可以: ChangeCaption(Edit1);
在这里,实际上是用了“多态”。因为 TEdit 和 TButton 都是从 TControl 继承下来的。
不过,在这里用多态,你传入的还是一个变数,当然,任何变数都是某个类别的。可能是 TButton,可能是 TEdit.
------------------------
但是,如果你都不知道你要处理的东东是个什么东东,是什么类别的东东,并且你要根据类别的不同,做不同的操作,那么:
TControl -- 一个类别定义
TButton --- 一个类别定义
TEdit --- 一个类别定义
TButtonClass = class of TButton -----类别 TButton 的引用!
TControlClass = class of TControl --- 类别 TControl 的引用!
AControlClass: TControlClass --- 定义了一个变数,这个变数不是一个类别的变数。可以看成它就是类别。它不可以做如下操作:
AControlClass := TControlClass.Create,不可以这样操作。而以个 Button1 := TButton.Create 是可以的!
不可以做这样的操作的原因是,AControlClass 本身就是一个类别定义,而不是一个普通的 TControl 类别的变数。
TMyControlClass = class of TMyControl ,这句话的意思,是定义了一个叫做 TMyControlClass 的类别,它代表对类别 TMyControl 的引用。似乎可以理解为它是 TMyControl 的一个别名。
因为它仅仅是一个类别定义的别名,你不可以 Create 它。因为它不是一个 Variant,仅仅是一个类别定义。
你定义一个 Var, 比如:
var
MyControl: TMyControl; 这个 var 是一个 TMyControl 类别的 var,它才是可以 Create 的一个具体的物件的名字
TMyControlClass = class of TMyControl , 不是子代,后代。
TMyControl2=class(TMyControl) 这个 TMycontrol2 才是 TMyControl 的子代,后代。
浙公网安备 33010602011771号