|
Usuários |
|
28 Usuários Online
|
|
[Artigos]
[Intermediário] -Use Class/Record Helpers no Delphi |
Publicado por rboaro : Domingo, Setembro 22, 2013 - 10:01 GMT-3 (354 leituras)
comentar Enviar para um amigo Versão para impressão
|
Você sabe o que vem a ser um Class Helper?
Class Helper é uma técnica da programação orientada a objetos que tem o intuito de estender as funcionalidades de uma classe, sem que seja necessário utilizar herança e sem que seja necessário alterar a classe original. Imagine o seguinte cenário. Em sua aplicação existe a classe TPessoa, que por algum motivo você não pode alterar a sua implementação, mas, necessita de um determinado método nesta classe, como por exemplo retornar a idade da pessoa a partir de sua data de nascimento.
Em situações normais, seria feito um método CalcularIdade() por exemplo e seria usado da seguinte forma:
{...}
EdtIdade.Text := IntToStr(CalcularIdade(oPessoa.DataNasc));
{...}
Agora imagine se fosse desta forma:
{...}
EdtIdade.Text := oPessoa.Idade.ToString;
{...}
Muito mais claro e limpo. Mas como fazer isso sem ter acesso a implementação da classe TPessoa? Simples, fazendo um Class Helper para a classe TPessoa. Faremos um exemplo bem simples para mostrar o uso prático do recurso. Vamos começar pela interface da classe TPessoa: type
TPessoa = class
private
FDataNasc: TDate;
public
property DataNasc : TDate read FDataNasc write FDataNasc;
end;
Usaremos somente o campo referente a data de nascimento, pois ele está no foco do nosso exemplo. Agora faremos o nosso Class Helper para a classe TPessoa:
type
TPessoaHelper = class helper for TPessoa
private
function GetIdade: integer;
public
property Idade : integer read GetIdade;
end;
implementation
uses
DateUtils,
System.SysUtils;
{ TPessoaHelper }
function TPessoaHelper.GetIdade: integer;
begin
Result := YearsBetween(Self.DataNasc,Now);
end;
Note que para determinar que uma classe é um class helper de outra é necessário utilizar a diretiva helper e indicar a classe principal com a palavra reservada for. Outro ponto que merece atenção é o fato de que, na classe helper, nós temos acesso a todos os atributos públicos da classe principal a partir da própria instância do helper, por esse motivo que foi possível acessar a propriedade DataNasc.
Pronto, agora a propriedade Idade já está disponível para todos os objetos do tipo TPessoa em units que fizerem referência a unit do class helper (caso o class helper TPessoaHelpertenha sido feito em uma unit diferente da unit da classe TPessoa).
Por exemplo:
uses
unt_pessoa,
unt_pessoa_helper;
procedure TForm1.Button1Click(Sender: TObject);
var
oPessoa : TPessoa;
begin
oPessoa := TPessoa.Create;
try
oPessoa.DataNasc := StrToDate('26/11/1986');
EdtIdade.Text := IntToStr(oPessoa.Idade);
finally
oPessoa.Free;
end;
end;
Mas nosso exemplo ainda não terminou. Note que ainda estou fazendo um type castingexplícito na idade, como resolver isso? Utilizando Record Helper :) . A partir do Delphi XE3, é possível criar helpers para tipos primitivos, como por exemplo o tipo integer. Faremos um record helper para o tipo integer com o simples intuito de converter o inteiro para uma string:
TIntHelper = record helper for integer
public
function ToString():String;
end;
implementation
function TIntHelper.ToString: String;
begin
Result := IntToStr(Self);
end;
Agora sim, nosso exemplo está completo:
procedure TForm1.Button1Click(Sender: TObject);
var
oPessoa : TPessoa;
begin
oPessoa := TPessoa.Create;
try
oPessoa.DataNasc := StrToDate('26/11/1986');
EdtIdade.Text := oPessoa.Idade.ToString;
finally
oPessoa.Free;
end;
end;
Vale lembrar que utilizando o helper TIntHelper que criamos, abrimos margem para substituir a clássica conversão StrToInt para simplesmente utilizar a nossa funçãoToString():
var
iNumero : integer;
sTexto : string;
begin
sTexto := 1.ToString; //sTexto = '1'
iNumero := 2;
sTexto := iNumero.ToString; //sTexto = '2'
end;
Mas antes de sair criando helpers para tipos conhecidos, verifique se o próprio Delphi já não disponibiliza um helper para o mesmo intuito. A unit SysUtils possui uma série de helpers para os tipos mais comumente utilizados. Uma dúvida que sempre aparece quando se começa a utilizar class helpers é com relação a criação de mais de um helper para uma determinada classe. Por exemplo, o seguinte código não funciona da maneira que intuitivamente se espera:
TPessoaHelper = class helper for TPessoa
private
function GetIdade: integer;
public
property Idade : integer read GetIdade;
end;
TPessoaFisicaHelper = class helper for TPessoa //esse passa a ser o Helper "ativo"
public
function isValidCPF():Boolean;
end;
Não ocorre um erro de compilação, porém, a propriedade Idade, não estará mais disponível, pois um helper se sobrepõe ao outro. Para que isso não ocorra, é necessário indicar o class helper antecessor, desta forma:
TPessoaHelper = class helper for TPessoa
private
function GetIdade: integer;
public
property Idade : integer read GetIdade;
end;
TPessoaFisicaHelper = class helper (TPessoaHelper) for TPessoa
public
function isValidCPF():Boolean;
end;
TPessoaJuridicaHelper = class helper (TPessoaFisicaHelper) for TPessoa
public
function isValidCNPJ():Boolean;
end;
Devido a evoluções que a arquitetura do Delphi vem sofrendo, principalmente pelas inovações relacionadas a mobilidade, a própria Embarcadero recomenda que se use classe/record helpers para determinados fins, fazendo com que o seu código esteja protegido de eventuais mudanças mais trágicas, como por exemplo a promessa de extinção da concatenação de strings através do simbolo de adição (Ex: Str1 := ‘Texto ‘ + IntToStr(3));
Diego Garcia
http://drgarcia1986.wordpress.com
http://twitter.com/drgarcia1986
https://github.com/drgarcia1986
|
|
Comentários | |
| | Comentários pertencem aos seus respectivos autores. Não somos responsáveis pelo seus conteúdos. |
|
|
Edição 112 |
|
|
50 Programas Fontes |
|
|
Produtos |
|
|