Olá pessoal, neste artigo vou demonstrar alguns exemplos básicos de como a nova RTTI (RunTime Type Information) pode facilitar o desenvolvimento deixando nossas aplicações mais abstratas. A definição mais básica sobre RTTI seria uma variedade de informações que o compilador disponibiliza sobre os Tipos (Classes) em tempo de execução, essas informações podem ser consultadas e alteradas caso as mesmas sejam propriedades.
Esse recurso sempre esteve presente no Delphi, mas existiam algumas limitações tais como: as classes teriam que possuir a diretiva {$M+} ou serem descendentes de uma classe que possuía essa diretiva, só assim as informações poderiam ser lidas, as propriedades deveriam estar declaradas na seção published e mesmo assim o compilador ainda não fornecia informações tão precisas sobre os tipos dos objetos. A partir do Delphi 2010 a RTTI foi devidamente reformulada, incrementada e documentada.
Atualmente existem muitos exemplos de uso da RTTI na internet, nesse artigo vou demonstrar exemplos relacionados à alguns componentes da VCL, veremos como obter informações dos componentes do Form em tempo de execução e modificaremos as propriedades dos mesmos.
Uma técnica interessante para ser usada quando trabalhamos com RTTI é o TypeCast, para melhor definir essa técnica encontrei essa definição.
”Trata-se de uma forma de “forçar” o compilador a enxergar, considerar, uma variável, um valor, um objeto de um tipo específico como se fosse outro tipo. Entenda “Objeto” como uma instância de uma classe, uma variável que aloca memória dinamicamente para um determinado tipo de classe.”
A grande maioria dos eventos ligados a objetos da VCL passa como parâmetro Sender que é um ponteiro para o objeto que disparou o evento, esse ponteiro é do tipo TObject, como mostra o exemplo da figura 1, com esse parâmetro podemos fazer um TypeCast para determinado componente.
procedure TForm1.Button1Click(Sender: TObject);
begin
end;
Para se fazer um TypeCast é muito simples, a própria RTTI nos fornece 2 operadores “is” e “as”, sabendo usá-los podemos atingir um código legível e ao mesmo tempo seguro contra exceptions. Podemos usar o operador “is” para verificar se Sender é do tipo TButton, ou seja, o objeto que disparou o evento OnClick essa informação conseguimos através da RTTI isso tudo em tempo de execução, caso seja do tipo TButton podemos posteriormente usar o operador “as” para alterar qualquer propriedade de Sender, ou seja, modificar o caption, hint, cursor e etc., como mostra a figura 2.
procedure TForm1.Button1Click(Sender: TObject);
begin
if (Sender is TButton) then
begin
(Sender as TButton).Caption := ‘DevMedia !’;
end;
end;
Agora vamos criar um exemplo prático, abrir um novo projeto no Delphi e adicionar os seguintes componentes:
- 3 - TEdit
- 1 - Tmemo
- 1 - TButton(name=”btnLimparCampos”)
Adicionei um texto simples para cada um dos Edits e para Memo como mostrado na figura 2.
Nesse exemplo vamos usar a RTTI e o TypeCast para limpar todos os Edits e o TMemo, normalmente poderíamos disparar a procedure Clear() para cada um dos componentes, mas nesse exemplo vamos usar um contador e coletar informações sobre os componentes em tempo de execução e posteriormente limpá-los. No evento OnClick do btnLimparCampos vamos digitar o código como mostrado na Listagem 1.
procedure TForm1.btnLimpaCamposClick(Sender: TObject);
var
i: Integer;
begin
//Contador que verifica todos os componentes do Form
for i := 0 to ComponentCount -1 do
begin
//Verifica se o objeto é do tipo TEdit
if (Components[i] is TEdit) then
(Components[i] as TEdit).Clear;
//Verifica se o objeto é do tipo TMemo
if (Components[i] is TMemo) then
(Components[i] as TMemo).Clear;
end;
end;
Agora vamos executar a aplicação e pressionar o botão Limpar Campos para visualizar o resultado como mostra a figura 3.
Com esse código podemos limpar os textos dos devidos componentes sem precisar disparar individualmente a procedure Clear(), através das informações que o compilador passa em tempo de execução podemos simplesmente capturar os componentes do Form e fazer um TypeCast para verificar se o componente é realmente o que desejamos limpar. Quando trabalhamos OO é interessante usar esse tipo de procedure para limpeza de campos, imagine um Form com vários Edits e após uma inserção no banco de dados termos que limpar todos os campos para iniciar a próxima operação, seria muito trabalhoso.
É bom mencionar que existe outro tipo de TypeCast, é o HardCast. Essa técnica embora exista opiniões que sua velocidade seja melhor que usando os operadores “as” e “is”, não é muito aconselhável, pois ela não testa como demonstrada no exemplo da figura 2, se Sender é do tipo que desejamos trabalhar, então porque usá-la se podemos ter todas as informações sobre o objeto em tempo de execução através da RTTI. Não precisamos arriscar em usar o HardCast e gerar possivelmente uma exception Access Violation, por esse motivo recomendo usar os operadores.