代码之家  ›  专栏  ›  技术社区  ›  Alin Sfetcu

使用他的类类型强制转换为对象?

  •  5
  • Alin Sfetcu  · 技术社区  · 17 年前

    如何使我的代码工作?:)我试着提出这个问题,但在几次失败的尝试之后,我想你们会更快地发现问题,看代码比阅读我的“解释”。谢谢您。

    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;
    
    5 回复  |  直到 17 年前
        1
  •  5
  •   Remy Lebeau    17 年前

    使用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;
    
        2
  •  7
  •   zendar    17 年前

    必须将对象显式转换为某个类。 这应该有效:

     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;
    
        3
  •  4
  •   Reed Copsey    17 年前

    在设置对象的属性之前,需要将CT对象强制转换为tmemo/tedit/tbutton。

    因为CT仍然是Tclass,而不是Tbutton/etc,所以您得到错误的行是错误的。如果您强制转换为Tbutton,那么您将能够将Enabled设置为true。

    我建议阅读 casting in Delphi . 我个人也建议使用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;
    
        4
  •  3
  •   Alex    17 年前

    不需要分别强制转换到tmemo和tedit,因为它们都是具有只读属性的公共父类的后代:

    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;
    
        5
  •  2
  •   Ryan VanIderstine    17 年前

    如果您不介意一个小的性能冲击并限制对已发布属性的更改,则可以避免引用各种单元和显式强制转换。看看Delphi中包含的typinfo单元。

    推荐文章