簡體   English   中英

使用他的ClassType轉換TObject?

[英]cast TObject using his ClassType?

我怎樣才能使我的代碼工作? :)我試圖制定這個問題,但經過幾次失敗的嘗試后,我認為你們會更快地發現問題,而不是閱讀我的“解釋”。 謝謝。

setCtrlState([ memo1, edit1, button1], False);

_

procedure setCtrlState(objs: array of TObject; bState: boolean = True);
var
  obj: TObject;
  ct: TClass;
begin
  for obj in objs do
  begin
    ct := obj.ClassType;


    if (ct = TMemo) or (ct = TEdit) then
      ct( obj ).ReadOnly := not bState;        // error here :(

    if ct = TButton then
      ct( obj ).Enabled:= bState;        // and here :(

  end;
end;

您必須顯式地將對象強制轉換為某個類。 這應該工作:

 procedure setCtrlState(objs: array of TObject; bState: boolean = True);
 var
   obj: TObject;
   ct: TClass;
 begin
  for obj in objs do
  begin
    ct := obj.ClassType;

    if ct = TMemo then
      TMemo(obj).ReadOnly := not bState
    else if ct = TEdit then
      TEdit(obj).ReadOnly := not bState
    else if ct = TButton then
      TButton(obj).Enabled := bState;
  end;
end;

這可以使用“ is ”運算符縮短 - 不需要ct變量:

 procedure setCtrlState(objs: array of TObject; bState: boolean = True);
 var
   obj: TObject;
 begin
   for obj in objs do
   begin
     if obj is TMemo then
       TMemo(obj).ReadOnly := not bState
     else if obj is TEdit then
       TEdit(obj).ReadOnly := not bState
     else if obj is TButton then
       TButton(obj).Enabled := bState;
   end;
 end;

使用RTTI而不是顯式轉換會更容易,即:

uses
  TypInfo;

setCtrlState([ memo1, edit1, button1], False);

procedure setCtrlState(objs: array of TObject; bState: boolean = True);
var
  obj: TObject;
  PropInfo: PPropInfo;
begin
  for obj in objs do
  begin
    PropInfo := GetPropInfo(obj, 'ReadOnly');
    if PropInfo <> nil then SetOrdProp(obj, PropInfo, not bState);

    PropInfo := GetPropInfo(obj, 'Enabled');
    if PropInfo <> nil then SetOrdProp(obj, PropInfo, bState);
  end;
end;

在設置對象的屬性之前,需要將ct對象強制轉換為TMemo / TEdit / TButton。

你遇到錯誤的行是錯誤的,因為ct仍然是TClass,而不是TButton /等。 如果你轉換為TButton,那么你將能夠將enabled設置為true。

我建議閱讀Delphi中的cast 就個人而言,我建議使用as / is運算符,而不是使用ClassType。 在這種情況下,代碼將更簡單,更容易理解。


就個人而言,我會更喜歡這樣寫:

procedure setCtrlState(objs: array of TObject; bState: boolean = True);
var
  obj: TObject;
begin
  for obj in objs do
  begin
    // I believe these could be merged by using an ancestor of TMemo+TEdit (TControl?)
    // but I don't have a good delphi reference handy
    if (obj is TMemo) then
        TMemo(obj).ReadOnly := not bState;

    if (obj is TEdit) then
        TEdit(obj).ReadOnly := not bState;

    if (obj is TButton) then
        TButton(obj).Enabled := bState;
  end;
end;

沒有必要單獨轉換為TMemo和TEdit,因為它們都是來自公共父類的后代,它具有ReadOnly屬性:

procedure TForm1.FormCreate(Sender: TObject);

  procedure P(const Obj: TComponent);
  begin
    if Obj is TCustomEdit then
      TCustomEdit(Obj).ReadOnly := True;
  end;

begin
  P(Memo1);
  P(Edit1);
end;

如果您不介意小的性能損失並限制對已發布屬性的更改,則可以避免引用各種單位和顯式轉換。 看看Delphi附帶的TypInfo單元。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM