我是小白,今天碰到一个问题,就是比如说我一个string的变量str,里面的内容是'TForm'或者某个变量比如TForm的一个实例'form1',我该怎么写才能通过str来调用TForm或者form1?

解决方案 »

  1.   

    一般是做个类似的对应表,通过实际类创建; 调用同理function GetObjByClzName(const AClzName : string; AOwner : TObject = nil): TObject;
    begin
      if AClzName = 'TForm' then
        Result := TForm.Create(AOwner)
      else
      if AClzName = 'TForm1' then
        Result := TForm1.Create(AOwner)
      else
        Result := nil;
    end;
      

  2.   


    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TBaseClass=class of  TBase;
      TForm1 = class(TForm)
        T1: TButton;
        procedure FormCreate(Sender: TObject);
        procedure T1Click(Sender: TObject);
      private
        { Private declarations }
        procedure CreateObjectByName( const ObjectName : string);
      public
        { Public declarations }
      end;
       TBase = class(TPersistent)
       public
          procedure Load;virtual;
        end;   TC1=class(TBase)
       public
          procedure Load;override;
       end;   TC2=class(TBase)
       public
          procedure Load;override;
       end;
    var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);
    begin
      RegisterClass(TBase);
      RegisterClass(TC1);
      RegisterClass(TC2);
    end;
    { TC2 }procedure TC2.Load;
    begin
      inherited;
       ShowMessage('TC2.Load');
    end;{ TBase }procedure TBase.Load;
    begin
       ShowMessage('TBase.Load');
    end;{ TC1 }procedure TC1.Load;
    begin
      inherited;
      ShowMessage('TC1.Load');
    end;procedure TForm1.CreateObjectByName(
      const ObjectName : string);
    var
      fc : TBaseClass;
      f : TBase;
    begin
      fc := TBaseClass(FindClass(ObjectName));
      f := fc.Create();
      f.Load;
     
    end;
    procedure TForm1.T1Click(Sender: TObject);
    begin
      CreateObjectByName('TC2');
    end;end.
      

  3.   

    TBase = class(TPersistent)
      private
        FValue: Variant;
        procedure SetValue(const Value: Variant);
       public
         constructor Create;
          procedure Load;virtual;
         property Value : Variant read FValue write SetValue;
        end;   TC1=class(TBase)
       public
          constructor Create(const Value : integer);
          procedure Load;override;
       end;   TC2=class(TBase)
       public
         constructor Create(const Value : string);
          procedure Load;override;
       end;
    如果子类的构造函数重写, 该如何写
    constructor TBase.Create;
    begin
      //禁止使用基础类创建
      raise Exception.Create('Error Message');
    end;constructor TC2.Create(const Value: string);
    begin
      FValue := Value;
    end;
      

  4.   

    这段代码中有两个问题
    1:一般RegisterClass是写在initialization中,而在finalization中写unRegisterClass。这样的好处是,注册类一般用于序列化,而序列化并不依赖于某个类的构造。再者,即便class list中不会出现重复,你将RegisterClass放在构造函数中,每次创建实例的时候都调用也很没必要的。放在init和final中的好处还在于,如果该单元被package引用,则在包的加载和卸载时,能够正确的注册和注销class,单元的重用相对简单和可靠。
    2:FindClass的时候,一定要判定返回值是否为nil,如果只是照着这个示例的写法,一旦出现没有注册的class,程序包出来的错位会很诡异,难于调试。