Class-reference types 類引用類型--快要失傳的技術

先摘一段原版的說明:

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的技術,去看幫助就明白了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章