类字段不在后代之间共享

Mar*_*lot 2 delphi oop delphi-11-alexandria

我可以在每个后代类上将一个字段声明为静态字段,而不是为所有后代类共享其值吗?

这是基类:

type
  TKpModelViewControllerEntity = class(TInterfacedObject, IKpEntity)
  protected
    class var ResourceName: string; 
    procedure Manage;  
  public
    class function Create: IKpEntity;
  end;
Run Code Online (Sandbox Code Playgroud)

这是后裔

unit Customers;

type
  TCustomers = class(TKpModelViewControllerEntity)
  end;

initialization
  TCustomers.ResourceName := 'customers/';
Run Code Online (Sandbox Code Playgroud)

还有另一个:

unit Articles;

type
  TArticles = class(TKpModelViewControllerEntity)
  end;

initialization
  TArticles.ResourceName := 'articles/';
Run Code Online (Sandbox Code Playgroud)

当我尝试创建“客户”屏幕 ( TCustomers.Create.Manage) 时,其资源名称具有“articles/”值而不是“customers/”。

有没有办法指示静态字段为每个后代类保存单独的值?

谢谢。

Uwe*_*abe 5

这可以通过属性轻松实现:

type
  ResourceNameAttribute = class(TCustomAttribute)
  private
    FValue: string;
  public
    constructor Create(const AValue: string);
    property Value: string read FValue;
  end;

type
  TKpModelViewControllerEntity = class(TInterfacedObject, IKpEntity)
  protected
    class function ResourceName: string;
    procedure Manage;
  public
    class function Create: IKpEntity;
  end;

class function TKpModelViewControllerEntity.ResourceName: string;
begin
  Result := '';
  var ctx := TRttiContext.Create;
  var cls := ctx.GetType(Self);
  var attr := cls.GetAttribute<ResourceNameAttribute>;
  if attr <> nil then
    Result := attr.Value;
end;

constructor ResourceNameAttribute.Create(const AValue: string);
begin
  inherited Create;
  FValue := AValue;
end;

...

type
  [ResourceName('customers/')]
  TCustomers = class(TKpModelViewControllerEntity)
  end;

type
  [ResourceName('articles/')]
  TArticles = class(TKpModelViewControllerEntity)
  end;
Run Code Online (Sandbox Code Playgroud)


Rem*_*eau 5

我会使用一个class virtual方法而不是一个class var,例如:

type
  TKpModelViewControllerEntity = class(TInterfacedObject, IKpEntity)
  protected
    class function ResourceName: string; virtual;
    ...
  end;

class function TKpModelViewControllerEntity.ResourceName: string;
begin
  Result := ''; // or whatever default you want...
end;
Run Code Online (Sandbox Code Playgroud)
type
  TCustomers = class(TKpModelViewControllerEntity)
  protected
    class function ResourceName: string; override;
    ...
  end;

class function TCustomers.ResourceName: string;
begin
  Result := 'customers/';
end;
Run Code Online (Sandbox Code Playgroud)
type
  TArticles = class(TKpModelViewControllerEntity)
  protected
    class function ResourceName: string; override;
    ...
  end;

class function TArticles.ResourceName: string;
begin
  Result := 'articles/';
end;
Run Code Online (Sandbox Code Playgroud)

  • @MarcGuillot 当然,使用属性会起作用。请注意,它们会向您编译的可执行文件添加更多 RTTI。而该解决方案根本不使用任何 RTTI。 (2认同)