TObject的投用他的类类别?(cast TObject using his ClassType?

2019-09-17 16:01发布

我怎样才能让我的代码工作? :) i`ve试图制定这个问题,但多次失败的尝试后,我想你们一定会发现问题快看代码比读我的“解释”。 谢谢。

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;

Answer 1:

这将是更容易使用,而不是明确的铸造,即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;


Answer 2:

你必须明确地转换对象的一些类。 这应该工作:

 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;


Answer 3:

您需要将CT目标转换为TMemo / TEDIT / TButton的前可以设置对象的属性。

你得到的错误,其中线示数,因为CT仍然是一个TClass,不是一个TButton /等。 如果你投以一个TButton,那么你就可以设置启用为true。

我建议在阅读了在Delphi铸造 。 就个人而言,我会建议使用AS /是运营商,而不是使用类类别,以及。 该代码将在这种情况下,简单,更易懂。


就个人而言,我会写这更像是:

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;


Answer 4:

有没有必要投给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;


Answer 5:

你能避免引用各单位和显式转换,如果你不介意小的性能损失,并限制更改发布的属性。 看一看附带德尔福TypInfo单元。



文章来源: cast TObject using his ClassType?