字符串到类:转换类或基本转换方法?

时间:2015-12-08 13:29:30

标签: class delphi model delphi-2009

我正在开发一个项目,在这个项目中,我建立了一个由基本类“TFuncao”,两个后代类“TSolicitacao”,“TResposta”和尽可能多的后代类构成的结构,所有这些类都是类的 - 只有属性的模型。

第一个是这个问题的焦点,它有一个方法“ParaTexto”,它以特定的方式返回所有属性的字符串(基本上将它们转换为字符串)。 “TSolicitacao”类有许多后代,每个类都有方法“ParaTexto”调用它的祖先函数并添加它自己的属性。

所以,我的问题是:

我应该保留这种方法“ParaTexto”吗?或者删除它并使用接收“TSolicitacao”的方法创建一个类,因此它的类型(后代类)返回一个字符串?

我想到了这一点,因为模型类在技术上应该只有getter和setter。

代码 - 为了节省空间而移除的getter和setter:

“TFuncao”类文件:

unit Funcao;

interface

uses
  Funcao.Tipo;

type
  TFuncao = class abstract
  private
    FFUNCAO: TFuncaoTipo;
    FSEQUENC: string;
    procedure SetFUNCAO(const Value: TFuncaoTipo);
    procedure SetSEQUENC(const Value: string);
  published
    property SEQUENC: string read FSEQUENC write SetSEQUENC;
    property FUNCAO: TFuncaoTipo read FFUNCAO write SetFUNCAO;
    constructor Create; virtual;
  end;

“TSolicitacao”类文件:

unit Funcao.Solicitacao;

interface

uses
  Funcao;

type
  TSolicitacao = class abstract (TFuncao)
  published
    function ParaTexto: string; virtual;
  end;

implementation

uses
  Funcoes,
  SysUtils;

{ TSolicitacao }

function TSolicitacao.ParaTexto: string;
begin
  Result :=
    Copy(CompletarComEspacoAEsquerda(SEQUENC, 4), 1, 4) +
    Completar0AEsquerda(IntToStr(Integer(FUNCAO)), 2);
end;

end.

“TVendaSolicitacao”类文件 - “TSolicitacao”的后代类示例:

unit Venda.Solicitacao;

interface

uses
  Funcao.Solicitacao,
  Funcao.Tipo,
  Venda.Solicitacao.Produto;

type
  TVendaSolicitacao = class (TSolicitacao)
  private
    FNUMFISCAL: Integer;
    FNUMPDV: Integer;
    FAUTORIZ: string;
    FCONV_TIPO: Integer;
    FProdutos: TVendaSolicitacaoProdutoList;
    procedure SetAUTORIZ(const Value: string);
    procedure SetCONV_TIPO(const Value: Integer);
    procedure SetNUMFISCAL(const Value: Integer);
    procedure SetNUMPDV(const Value: Integer);
    procedure SetProdutos(const Value: TVendaSolicitacaoProdutoList);
  published
    property NUMPDV: Integer read FNUMPDV write SetNUMPDV;
    property NUMFISCAL: Integer read FNUMFISCAL write SetNUMFISCAL;
    property AUTORIZ: string read FAUTORIZ write SetAUTORIZ;
    property CONV_TIPO: Integer read FCONV_TIPO write SetCONV_TIPO;
    property Produtos: TVendaSolicitacaoProdutoList read FProdutos write SetProdutos;
    function ParaTexto: string; override;
    constructor Create; override;
  end;

implementation

uses
  SysUtils,
  Funcoes;

{ TVendaSolicitacao }

constructor TVendaSolicitacao.Create;
begin
  inherited;
  FUNCAO := ftVenda;
  FProdutos := TVendaSolicitacaoProdutoList.Create;
end;

function TVendaSolicitacao.ParaTexto: string;
begin
  Result :=
    inherited +
    Completar0AEsquerda(NUMPDV, 4) +
    Completar0AEsquerda(NUMFISCAL, 6) +
    Completar0AEsquerda(AUTORIZ, 12) +
    IntToStr(CONV_TIPO);

  if Produtos.Count > 0 then
    Result := Result + #13#10 + Produtos.ParaTexto;
end;

end.

“TConversao”类文件 - 我认为:

unit Conversao;

interface

uses
  Funcao;

type
  TConversao = class
  published
    function ParaTexto(Funcao: TFuncao): string;
  end;

implementation

uses
  Solicitacao,
  Solicitacao.Venda,
  Funcoes;

function ParaTexto(Funcao: TFuncao): string;
begin
  Result := '';

  if (Funcao is TSolicitacao) then
    Result :=
      Copy(CompletarComEspacoAEsquerda((Funcao as TSolicitacao).SEQUENC, 4), 1, 4) +
      Completar0AEsquerda(IntToStr(Integer((Funcao as TSolicitacao).FUNCAO)), 2);

  if (Funcao is TVendaSolicitacao) then
  begin
    Result :=
      inherited +
      Completar0AEsquerda((Funcao as TVendaSolicitacao).NUMPDV, 4) +
      Completar0AEsquerda((Funcao as TVendaSolicitacao).NUMFISCAL, 6) +
      Completar0AEsquerda((Funcao as TVendaSolicitacao).AUTORIZ, 12) +
      IntToStr((Funcao as TVendaSolicitacao).CONV_TIPO);

    if Produtos.Count > 0 then
      Result := Result + #13#10 + Produtos.ParaTexto;
  end;

1 个答案:

答案 0 :(得分:1)

是的,您应该保留此方法,这样代码更具可读性和可重用性。比如,你定义了TSolicitacao的新后代,你重写ParaTexto就是这样。所有更改都在一个地方 - 在您的班级定义中。

您还可以尝试使用RTTI迭代类的所有属性并自动生成字符串。

<强>更新

一些提示如何使用RTTI(工作示例)。您可以定义不同类型的整数:

  T7digitsInt = type Int64;
  T8digitsInt = type Int64;

此外,用于从Int64转换为字符串的函数类型:

TConvertCustomIntToStringProc = function (num: Int64): string;

某些具有属性的测试类,类似于TSolicitacao:

  TEntry = class (TObject)
    private
      fPlainInt: Int64;
      f7digitInt: T7digitsInt;
      fWriteOnlyInt: T7digitsInt;
      f8digitInt: T8digitsInt;
    published
      property PlainInt: Int64 read fPlainInt write fPlainInt;
      property NotSoPlainInt: T7digitsInt read f7digitInt write f7digitInt;
      property AnotherInt: T7digitsInt write fWriteOnlyInt;
      property Biggest: T8digitsInt read f8digitInt write f8digitInt;
  end;

此外,我们在单位中声明全局变量,这是不同属性类型的列表:

var PropertyConverters: TDictionary<string, TConvertCustomIntToStringProc>;

现在,在实现部分中,我们定义了一些将整数转换为字符串的函数:

function ShowPlainInt64(num: Int64): string;
begin
    Result:=IntToStr(num);
end;

function Show7digitsInt(num: Int64): string;
begin
    Result:=Format('%.7d',[num]);
end;

我们'注册'这个函数分别处理Int64和T7DigitsInt,在初始化的某个地方,例如在TForm1.create中:

procedure TForm1.FormCreate(Sender: TObject);
begin
  PropertyConverters:=TDictionary<string,  ConvertCustomIntToStringProc>.Create;
  PropertyConverters.Add('Int64',ShowPlainInt64);
  PropertyConverters.Add('T7digitsInt',Show7DigitsInt);
end;

在TForm1.FormShow中,我们创建TEntry的实例并用值填充它来测试我们的转换器,然后尝试访问它们,迭代属性:

procedure TForm1.FormShow(Sender: TObject);
var entry: TEntry;
    ctx : TRttiContext;
    rt : TRttiType;
    prop : TRttiProperty;
    convertProc: TConvertCustomIntToStringProc;
begin
  entry:=TEntry.Create;
  entry.PlainInt:=12;
  entry.NotSoPlainInt:=34;

  //iterating through all the properties with RTTI
  ctx := TRttiContext.Create();
    try
        rt := ctx.GetType(entry.ClassType);

        for prop in rt.GetProperties() do begin
          if prop.IsReadable then
            if PropertyConverters.TryGetValue(prop.PropertyType.Name,convertProc) then
              Memo1.Lines.Add(prop.Name+'='+convertProc(prop.GetValue(entry).AsOrdinal))
            else
              Memo1.lines.Add(prop.Name+':unregistered type')
          else
            Memo1.Lines.Add(prop.Name+':write-only');



        end;
    finally
        ctx.Free();
    end;

end;

这就是我得到的:

PlainInt=12
NotSoPlainInt=0000034
AnotherInt:write-only
Biggest:unregistered type

如你所见,我们有几个整数,它们只有不同的类型,因此我们以不同的方式显示它们。如果没有那么多类型,那么这样的代码可能非常有效。