Class-reference types 类引用类型--快要失传的技术

来源:互联网 发布:c语言bzero 编辑:程序博客网 时间:2024/04/30 15:43

先摘一段原版的说明:

A class-reference type, sometimes called a metaclass, is denoted by a construction of the form

class of type

where type is any class type. The identifier type itself denotes a value whose type is class of type. If type1 is an ancestor of type2, then class of type2 is assignment-compatible with class of type1. Thus

type TClass = class of TObject;
var AnyObj: TClass;

declares a variable called AnyObj that can hold a reference to any class. (The definition of a class-reference type cannot occur directly in a variable declaration or parameter list.) You can assign the value nil to a variable of any class-reference type.

To see how class-reference types are used, look at the declaration of the constructor for TCollection (in the Classes unit):

type TCollectionItemClass = class of TCollectionItem;
  ...
constructor Create(ItemClass: TCollectionItemClass);

This declaration says that to create a TCollection instance object, you must pass to the constructor the name of a class descending from TCollectionItem.

Class-reference types are useful when you want to invoke a class method or virtual constructor on a class or object whose actual type is unknown at compile time.


光看帮助你大概搞不清楚这个有什么用。我举一个例子,一般mainform都有很多菜单按钮,用来打开不同的窗口,通常做法要在uses部分添加所有要引用的单元,十分麻烦,用上面的技术就可以避免引用。假设所有的业务窗口都从TAppBasicForm继承,你可以声明这样的类型:

TTAppBasicFormClass = class of TTAppBasicForm;

然后在每个业务窗口代码结尾处加上:


initialization
  RegisterClass(TBusMemberNewForm); //TBusMemberNewForm从TAppBasicForm继承

finalization
  UnRegisterClass(TBusMemberNewForm);


最后在Mainform用下面的函数:

procedure TTMainForm.ShowForm(sFormClass: string);
var
  AppFormClass: TTAppBasicFormClass;
begin
  try
    AppFormClass := TTAppBasicFormClass(FindClass(sFormClass));
    with AppFormClass.Create(self) do begin
      Show;
    end;
  except
    ShowMessage('Class ‘+sFormClass+' not exist or not register!');
  end;
end;

这个函数的参数就是要打开的窗口类名


更进一步,因为项目中Menu的hint属性不会用到,可以用来存储要打开的类名,如下:

procedure TTMainForm.MainFormMenuClick(Sender: TObject);
var
  sFormName: string;
begin
  with sender as TMenuItem do begin
    sFormName := Trim(Hint);
    if sFormName<>'' then ShowForm(sFormName);
  end;
end;

procedure TTMainFaceForm.SetMenuAction;
var
  i: integer;
begin
  for i:=0 to ComponentCount-1 do begin
    if Components[i] is TMenuItem then begin
      with Components[i] as TMenuItem do
        if Trim(Hint)<>'' then OnClick := MainFormMenuClick;
    end;
  end;
end;


这样的话每增加一个菜单,只要指定菜单的hint属性就自动实现打开对应业务的功能,避免引用单元,也不用写菜单的onclick代码,非常简洁。当然这个还用到了RegisterClass和FindClass的技术,去看帮助就明白了。

原创粉丝点击