我正在开发一个项目,在这个项目中,我建立了一个由基本类“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;
答案 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
如你所见,我们有几个整数,它们只有不同的类型,因此我们以不同的方式显示它们。如果没有那么多类型,那么这样的代码可能非常有效。