delphi 子类之间未共享的类字段

ie3xauqp  于 2023-08-04  发布在  其他
关注(0)|答案(3)|浏览(77)

我可以在每个后代类上声明一个字段为static而不是为所有后代类共享它的值吗?
这是一个基类:

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

字符串
这是一个后代

unit Customers;

type
  TCustomers = class(TKpModelViewControllerEntity)
  end;

initialization
  TCustomers.ResourceName := 'customers/';


还有一个:

unit Articles;

type
  TArticles = class(TKpModelViewControllerEntity)
  end;

initialization
  TArticles.ResourceName := 'articles/';


当我尝试创建一个Customers屏幕(TCustomers.Create.Manage)时,它的Resourcename的值是“articles/”而不是“customers/"。
有没有一种方法可以指示静态字段为每个子类保存单独的值?.

  • 谢谢-谢谢
2g32fytz

2g32fytz1#

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

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;

字符串

gojuced7

gojuced72#

我会使用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;
type
  TCustomers = class(TKpModelViewControllerEntity)
  protected
    class function ResourceName: string; override;
    ...
  end;

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

class function TArticles.ResourceName: string;
begin
  Result := 'articles/';
end;
epggiuax

epggiuax3#

类字段/方法是静态字段,不存储在类示例数据中,所以它引用继承链中的第一个。
一个好的实践应该是:
1.定义一个接口,例如IResource,它声明了一个方法function GetResourceName: String
1.在TCustomersTArticles上实现该接口。
1.通过上述方法查询资源名称。

相关问题