Motivação

Durante o desenvolvimento de aplicações Delphi é comum a necessidade de adicionar aos componentes visuais algumas funcionalidades extras, como validação e formatação de dados. Para atender a esse tipo de situação, alguns programadores optam por utilizar herança, enquanto outros alteram diretamente o código fonte do componente. Essas, porém, não são as melhores soluções, pois a herança obriga a utilização de uma nova classe, ao invés do componente padrão, e a alteração do código fonte pode gerar problemas em outras partes do sistema que utilizem esse mesmo componente.

A fim de suprir essa demanda, a partir da versão 2006 o Delphi passou a contar com um recurso chamado Class Helper, tornando possível adicionar novos comportamentos aos componentes sem usar herança ou modificar o código fonte original.

img Saiba mais sobre a série de cursos sobre Delphi

Definição

No Delphi, Class Helper é um recurso que permite adicionar métodos e modificar comportamentos de componentes em tempo de execução, sem a necessidade de herdar a classe ou utilizar recursos de composição, fazendo parecer que a classe contém o novo comportamento desde sua criação.

Outro diferencial é que Class Helpers não se aplicam somente a componentes. Eles também permitem modificar classes de domínio criadas pelo desenvolvedor, adicionar métodos a estruturas do tipo record e tipos primitivos (introduzidos a partir da versão XE3). Nesse último caso, no entanto, não é possível adicionar propriedades.

Como criar

Na Listagem 1 é apresentada uma unit que implementa um Class Helper para adicionar ao componente TEdit a capacidade de validar seu texto, definindo se ele representa um CPF ou CNPJ.


    01	unit UnitEditDocumento;
    02	   
    03	interface
    04	
    05	uses
    06	   vcl.stdCtrls, SysUtils;
    07	
    08	type
    09	   TEditDocumento = class helper for TEdit
    10	   private
    11	      function TextoSemSinais: string;
    12	   public
    13	      function isPessoaFisica: boolean;
    14	      function isPessoaJuridica: boolean;
    15	end;
    16	
    17	implementation
    18	
    19	uses
    20	   UnitUtils;
    21	
    22	{ TEditDocumento }
    23	
    24	function TEditDocumento.TextoSemSinais: string;
    25	var
    26    //Retorna o texto sem caracteres especiais
    27	end;
    28	
    29	function TEditDocumento.isPessoaFisica: boolean;
    30	begin
    31	   result := length(TextoSemSinais) = 11;
    32	end;
    33	
    34	function TEditDocumento.isPessoaJuridica: boolean;
    35	begin
    36	   result := length(TextoSemSinais) = 14;
    37	end;
    38  end
    
Listagem 1. Class Helper para um TEdit agregar métodos de validação

Linha 9: sintaxe para declaração do Class Helper. Essa instrução indica que está sendo criado um Class Helper (que é uma classe) para modificar o componente TEdit;

Linhas 10 a 15: declaração dos métodos da classe;

Linhas 24 a 37: implementação dos métodos da classe.

Perceba que toda a estrutura do Class Helper é a mesma de uma classe convencional, alterando apenas a forma de declaração.

Como utilizar

Sempre que for necessário utilizar um componente que possua o novo comportamento, basta adicionar o nome da unit em que está declarado o Class Helper na seção uses. A partir disso, será possível acessar os novos métodos adicionados, conforme mostra a Listagem 2.


    01	procedure TForm5.Edit1Exit(Sender: TObject);
    02	begin
    03	   if Edit1.isPessoaFisica then
    04	      Label1.Caption:='Documento Pessoa Física'
    05	   else
    06	   begin
    07	      if Edit1.isPessoaJuridica then
    08	         Label1.Caption:='Documento Pessoa Jurídica'
    09	      else
    10	      begin
    11	         Label2.Caption:='Documento Inválido';
    12	         exit;
    13	      end;
    14	   end;
    15	end;
    
Listagem 2. Utilizando os métodos adicionados pelo Class Helper

Nesse código, estamos trabalhando com o evento OnExit do componente TEdit, e nas linhas 3 e 7 utilizamos os novos métodos adicionados pelo Class Helper.

Modificando métodos existentes

Além de adicionar novos métodos, o Class Helper permite que modifiquemos os métodos já existentes em um componente. Na Listagem 3 apresentamos um exemplo de modificação do método Clear para uma situação especial em um formulário onde os componentes TEdit que aceitam texto recebem a string “xxxx” ao serem limpos, e os que aceitam apenas números recebem o texto “0000”. Esse comportamento pode ser necessário em algumas telas do sistema, a partir das quais temos, por exemplo, que imprimir o conteúdo em impressoras matriciais. Nesses casos, em planilhas de formulário contínuo, os campos não podem aparecer em branco para não descaracterizar a impressão.


    01	Unit UnitEditMatricial;
    02	...
    03	type
    04	   TEditDocumento = class helper for TEdit
    05	   public
    06	      procedure Clear;
    07	   end;
    08	
    09	...
    10	
    11	procedure TEditDocumento.Clear;
    12	begin
    13	   if NumbersOnly then
    14	      Text:= StringOfChar('0',MaxLength)
    15	   else
    16	      Text:=StringOfChar('X',MaxLength);
    17	end;
    
Listagem 3. Class Helper para modificar um método já existente no TEdit

Agora, quando adicionarmos a referência a essa unit na seção uses e acionarmos o método Clear de um TEdit, esse novo método será executado, ao invés do procedimento padrão que elimina todo o texto do campo.

Motivação

Durante o desenvolvimento de aplicações Delphi é comum a necessidade de adicionar aos componentes visuais algumas funcionalidades extras, como validação e formatação de dados. Para atender a esse tipo de situação, alguns programadores optam por utilizar herança, enquanto outros alteram diretamente o código fonte do componente. Essas, porém, não são as melhores soluções, pois a herança obriga a utilização de uma nova classe, ao invés do componente padrão, e a alteração do código fonte pode gerar problemas em outras partes do sistema que utilizem esse mesmo componente.

A fim de suprir essa demanda, a partir da versão 2006 o Delphi passou a contar com um recurso chamado Class Helper, tornando possível adicionar novos comportamentos aos componentes sem usar herança ou modificar o código fonte original.

img Saiba mais sobre a série de cursos sobre Delphi

Definição

No Delphi, Class Helper é um recurso que permite adicionar métodos e modificar comportamentos de componentes em tempo de execução, sem a necessidade de herdar a classe ou utilizar recursos de composição, fazendo parecer que a classe contém o novo comportamento desde sua criação.

Outro diferencial é que Class Helpers não se aplicam somente a componentes. Eles também permitem modificar classes de domínio criadas pelo desenvolvedor, adicionar métodos a estruturas do tipo record e tipos primitivos (introduzidos a partir da versão XE3). Nesse último caso, no entanto, não é possível adicionar propriedades.

Como criar

Na Listagem 1 é apresentada uma unit que implementa um Class Helper para adicionar ao componente TEdit a capacidade de validar seu texto, definindo se ele representa um CPF ou CNPJ.


        01	unit UnitEditDocumento;
        02	   
        03	interface
        04	
        05	uses
        06	   vcl.stdCtrls, SysUtils;
        07	
        08	type
        09	   TEditDocumento = class helper for TEdit
        10	   private
        11	      function TextoSemSinais: string;
        12	   public
        13	      function isPessoaFisica: boolean;
        14	      function isPessoaJuridica: boolean;
        15	end;
        16	
        17	implementation
        18	
        19	uses
        20	   UnitUtils;
        21	
        22	{ TEditDocumento }
        23	
        24	function TEditDocumento.TextoSemSinais: string;
        25	var
        26    //Retorna o texto sem caracteres especiais
        27	end;
        28	
        29	function TEditDocumento.isPessoaFisica: boolean;
        30	begin
        31	   result := length(TextoSemSinais) = 11;
        32	end;
        33	
        34	function TEditDocumento.isPessoaJuridica: boolean;
        35	begin
        36	   result := length(TextoSemSinais) = 14;
        37	end;
        38  end
        
Listagem 1. Class Helper para um TEdit agregar métodos de validação

Linha 9: sintaxe para declaração do Class Helper. Essa instrução indica que está sendo criado um Class Helper (que é uma classe) para modificar o componente TEdit;

Linhas 10 a 15: declaração dos métodos da classe;

Linhas 24 a 37: implementação dos métodos da classe.

Perceba que toda a estrutura do Class Helper é a mesma de uma classe convencional, alterando apenas a forma de declaração.

Como utilizar

Sempre que for necessário utilizar um componente que possua o novo comportamento, basta adicionar o nome da unit em que está declarado o Class Helper na seção uses. A partir disso, será possível acessar os novos métodos adicionados, conforme mostra a Listagem 2.


        01	procedure TForm5.Edit1Exit(Sender: TObject);
        02	begin
        03	   if Edit1.isPessoaFisica then
        04	      Label1.Caption:='Documento Pessoa Física'
        05	   else
        06	   begin
        07	      if Edit1.isPessoaJuridica then
        08	         Label1.Caption:='Documento Pessoa Jurídica'
        09	      else
        10	      begin
        11	         Label2.Caption:='Documento Inválido';
        12	         exit;
        13	      end;
        14	   end;
        15	end;
        
Listagem 2. Utilizando os métodos adicionados pelo Class Helper

Nesse código, estamos trabalhando com o evento OnExit do componente TEdit, e nas linhas 3 e 7 utilizamos os novos métodos adicionados pelo Class Helper.

Modificando métodos existentes

Além de adicionar novos métodos, o Class Helper permite que modifiquemos os métodos já existentes em um componente. Na Listagem 3 apresentamos um exemplo de modificação do método Clear para uma situação especial em um formulário onde os componentes TEdit que aceitam texto recebem a string “xxxx” ao serem limpos, e os que aceitam apenas números recebem o texto “0000”. Esse comportamento pode ser necessário em algumas telas do sistema, a partir das quais temos, por exemplo, que imprimir o conteúdo em impressoras matriciais. Nesses casos, em planilhas de formulário contínuo, os campos não podem aparecer em branco para não descaracterizar a impressão.


        01	Unit UnitEditMatricial;
        02	...
        03	type
        04	   TEditDocumento = class helper for TEdit
        05	   public
        06	      procedure Clear;
        07	   end;
        08	
        09	...
        10	
        11	procedure TEditDocumento.Clear;
        12	begin
        13	   if NumbersOnly then
        14	      Text:= StringOfChar('0',MaxLength)
        15	   else
        16	      Text:=StringOfChar('X',MaxLength);
        17	end;
        
Listagem 3. Class Helper para modificar um método já existente no TEdit

Agora, quando adicionarmos a referência a essa unit na seção uses e acionarmos o método Clear de um TEdit, esse novo método será executado, ao invés do procedimento padrão que elimina todo o texto do campo.