Page 38 - Revista_60.pub
P. 38
A PROGRAMAR
CLASSES DE INFRAESTRUTURA: A CLASSE USING
Vejamos agora como construir a classe Using. programador o trabalho de o instanciar, embora sofra altera-
ções na sua implementação para evitar duplicação de códi-
type go. Vejamos então como ficam as suas implementações:
Using = class
public
class procedure New class procedure Using.New<T>
<T: class, constructor> (Obj: T; Action: TProc<T>);
(Action: TProc<T>); begin
static; try
end; Action(Obj);
finally
Obj.Free;
A sua declaração é simples o bastante… Nada mais do end;
que uma classe e um método estático. Este irá receber por end;
parâmetro um método anónimo – que será a ação a executar
sobre o objeto a instanciar - que por sua vez terá um parâme- class procedure Using.New<T>
tro genérico (que será obrigatoriamente uma classe – a classe (Action: TProc<T>);
begin
do objeto a instanciar). Vamos então ver como implementar New<T>(T.Create, Action);
este método: end;
class procedure Using.New<T> O novo método é semelhante ao antigo, com a dife-
(Action: TProc<T>); rença de que não instancia o objeto. Simplesmente executa
var a ação e liberta a memória no final. Já o método antigo pas-
Obj: T;
begin sa a usar o novo para cumprir o seu objetivo, passando-lhe
Obj := T.Create; por parâmetro o objeto já instanciado.
try
Action(Obj); Assim, a classe Using tornou-se mais versátil, admi-
finally tindo ser usada com objetos cujo construtor necessite ou não
Obj.Free; de parâmetros.
end;
end;
Este código parece familiar, não? É exatamente o mé- Aumentando ainda mais a versatilidade da class Using:
todo 2 mostrado anteriormente. Uma variável é declarada, a É possível dar ainda mais versatilidade a esta classe,
classe é instanciada, uma ação é executada com esse objeto, se por exemplo permitirmos que esta retorne um parâmetro
e a memória a ele alocada é no final liberta. resultante da ação sobre o objeto.
Na sua forma mais simples, a classe Using está já
completa. Uma classe de infraestrutura com um método estáti- type
co que permite ter uma forma diferente de gerir o tempo de Using = class
public
vida de um objeto. Claro que apresenta algumas limitações: class procedure New
Como o objeto é instanciado pela classe Using, e esta não <T: class, constructor>
tem como saber ao certo como o programador a quer instanci- (Obj: T; Action: TProc<T>);
overload; static;
ar, ela assume que o objeto será criado com recurso a um class procedure New
constructor sem parâmetros chamado Create. <T: class, constructor>
(Action: TProc<T>);
Vamos então ver agora como deixar a classe Using overload; static;
mais versátil, aceitando objetos previamente criados pelo pro- class function New
gramador, mas mantendo o restante funcionamento. <T: class, constructor; TResult>
(Obj: T; Action: TFunc<T>): TResult;
overload; static;
type class function New
Using = class <T: class, constructor; TResult>
public (Action: TFunc<T>): TResult;
class procedure New overload; static;
<T: class, constructor> end;
(Obj: T; Action: TProc<T>);
overload; static; Os dois novos métodos são clones dos dois anterio-
class procedure New
<T: class, constructor> res, apenas usando funções no lugar de procedimentos, e
(Action: TProc<T>); aceitando um segundo parâmetro genérico que será usado
overload; static; como tipo de dados de retorno.
end;
Esta seria a sua implementação:
Acrescentámos, portanto, um novo método estático que
permitirá receber por parâmetro o objeto já construído. O mé- class function Using.New<T, TResult>
todo anterior irá ficar, para os casos onde o construtor do (Obj: T; Action: TFunc<T>): TResult;
objeto a instanciar não tem parâmetros, poupando assim ao begin
try
38