{"id":992,"date":"2025-02-03T08:43:10","date_gmt":"2025-02-03T11:43:10","guid":{"rendered":"https:\/\/adrianosantostreina.com.br\/blog\/?p=992"},"modified":"2025-02-24T09:00:24","modified_gmt":"2025-02-24T12:00:24","slug":"o-que-sao-e-como-usar-class-helpers-no-delphi","status":"publish","type":"post","link":"https:\/\/adrianosantostreina.com.br\/blog\/o-que-sao-e-como-usar-class-helpers-no-delphi\/","title":{"rendered":"O que s\u00e3o e como usar Class Helpers no Delphi?"},"content":{"rendered":"\n<p>No Delphi, <strong>Class Helpers<\/strong> s\u00e3o um recurso \u00fatil para adicionar novos m\u00e9todos a uma classe j\u00e1 existente sem precisar modific\u00e1-la diretamente. Essa funcionalidade \u00e9 especialmente \u00fatil quando estamos trabalhando com classes de bibliotecas fechadas ou quando queremos estender funcionalidades sem alterar o c\u00f3digo original.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>Com um <strong>Class Helper<\/strong>, podemos definir m\u00e9todos adicionais para uma classe sem criar heran\u00e7a. Diferente da heran\u00e7a tradicional, que permite sobrescrever e modificar comportamentos, os helpers atuam como uma extens\u00e3o tempor\u00e1ria da classe original. Eles s\u00e3o amplamente utilizados para organizar c\u00f3digo e tornar a programa\u00e7\u00e3o mais flex\u00edvel e leg\u00edvel.<\/p>\n\n\n\n<p>No entanto, \u00e9 importante us\u00e1-los com cuidado, pois algumas limita\u00e7\u00f5es podem impactar sua utiliza\u00e7\u00e3o. Neste artigo, exploraremos como funcionam os <strong>Class Helpers<\/strong>, suas vantagens e desvantagens, e como aplic\u00e1-los de forma eficiente no Delphi.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>O que \u00e9 um Class Helper?<\/strong><\/h2>\n\n\n\n<p>No Delphi, um <strong>Class Helper<\/strong> \u00e9 uma maneira de estender uma classe existente sem modific\u00e1-la diretamente. Diferente da heran\u00e7a tradicional, onde criamos uma nova classe derivada da original, um <strong>Class Helper<\/strong> permite adicionar m\u00e9todos \u00e0 classe sem precisar alterar seu c\u00f3digo-fonte.<\/p>\n\n\n\n<p>Essa t\u00e9cnica \u00e9 \u00fatil quando trabalhamos com classes de bibliotecas fechadas (como <code>TStringList<\/code>, <code>TDateTime<\/code>, <code>TButton<\/code>, etc.), permitindo criar m\u00e9todos adicionais sem tocar na implementa\u00e7\u00e3o original.<\/p>\n\n\n\n<p>Os <strong>Class Helpers<\/strong> funcionam como uma &#8220;camada tempor\u00e1ria&#8221; sobre a classe, fornecendo m\u00e9todos auxiliares que podem ser usados como se fossem parte da pr\u00f3pria classe. Por\u00e9m, eles n\u00e3o permitem sobrescrever m\u00e9todos existentes nem adicionar propriedades ou vari\u00e1veis de inst\u00e2ncia.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Como funciona um Class Helper?<\/strong><\/h3>\n\n\n\n<p>Os <strong>Class Helpers<\/strong> funcionam como uma &#8220;extens\u00e3o&#8221; de uma classe existente. Ao definir um helper para uma determinada classe, o Delphi passa a reconhecer os m\u00e9todos adicionais como se fizessem parte dela.<\/p>\n\n\n\n<p>A sintaxe b\u00e1sica de um <strong>Class Helper<\/strong> \u00e9 a seguinte:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \" >type\n  TMinhaClasseHelper = class helper for TClasseOriginal\n    function NovoMetodo: string;\n  end;\n<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>TMinhaClasseHelper<\/code>: Nome do helper que estamos criando.<\/li>\n\n\n\n<li><code>class helper for TClasseOriginal<\/code>: Indica que este helper est\u00e1 estendendo a classe <code>TClasseOriginal<\/code>.<\/li>\n\n\n\n<li><code>function NovoMetodo: string;<\/code>: M\u00e9todo que estamos adicionando \u00e0 classe.<\/li>\n<\/ul>\n\n\n\n<p>Agora, vamos aplicar isso a um exemplo pr\u00e1tico com <code>TStringList<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Exemplo pr\u00e1tico: Criando um Class Helper para TStringList<\/strong><\/h3>\n\n\n\n<p>Suponha que queremos adicionar um m\u00e9todo \u00e0 classe <code>TStringList<\/code> para obter o \u00faltimo item da lista. Sem um helper, precisar\u00edamos escrever essa l\u00f3gica manualmente sempre que precis\u00e1ssemos. Com um <strong>Class Helper<\/strong>, podemos encapsular esse comportamento de forma reutiliz\u00e1vel:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \" >type\n  TStringListHelper = class helper for TStringList\n    function GetUltimoItem: string;\n  end;\n  \nimplementation\n\nfunction TStringListHelper.GetUltimoItem: string;\nbegin\n  if Count &gt; 0 then\n    Result := Strings[Count - 1]\n  else\n    Result := '';\nend;\n<\/pre><\/div>\n\n\n\n<p>Agora, podemos usar esse novo m\u00e9todo como se fosse parte do <code>TStringList<\/code>:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \" >var\n  Lista: TStringList;\nbegin\n  Lista := TStringList.Create;\n  try\n    Lista.Add('Primeiro');\n    Lista.Add('Segundo');\n    Lista.Add('Terceiro');\n\n    ShowMessage(Lista.GetUltimoItem); \/\/ Exibe \"Terceiro\"\n  finally\n    Lista.Free;\n  end;\nend;\n<\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Principais Caracter\u00edsticas de um Class Helper<\/strong><\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Extens\u00e3o sem Heran\u00e7a<\/strong> \u2013 Voc\u00ea pode adicionar m\u00e9todos a uma classe sem criar uma subclasse.<\/li>\n\n\n\n<li><strong>N\u00e3o altera a classe original<\/strong> \u2013 A implementa\u00e7\u00e3o original permanece intacta.<\/li>\n\n\n\n<li><strong>M\u00e9todos apenas, sem novas propriedades ou vari\u00e1veis<\/strong> \u2013 Diferente da heran\u00e7a, helpers n\u00e3o podem ter propriedades ou campos privados.<\/li>\n\n\n\n<li><strong>Apenas um helper ativo por classe<\/strong> \u2013 Se houver mais de um helper para a mesma classe, apenas o \u00faltimo declarado ser\u00e1 utilizado.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Quando usar um Class Helper?<\/strong><\/h3>\n\n\n\n<p>Os <strong>Class Helpers<\/strong> s\u00e3o \u00fateis quando queremos:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Adicionar m\u00e9todos de utilidade a classes existentes.<\/li>\n\n\n\n<li>Extender classes de bibliotecas sem alterar seu c\u00f3digo-fonte.<\/li>\n\n\n\n<li>Melhorar a reutiliza\u00e7\u00e3o de c\u00f3digo, tornando-o mais organizado e leg\u00edvel.<\/li>\n<\/ul>\n\n\n\n<p>No entanto, devemos us\u00e1-los com cautela, pois sua utiliza\u00e7\u00e3o excessiva pode gerar c\u00f3digo dif\u00edcil de manter, principalmente quando h\u00e1 m\u00faltiplos helpers para uma mesma classe.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Criando um Class Helper para TEdit<\/strong><\/h2>\n\n\n\n<p>Nosso objetivo \u00e9 permitir que um <code>TEdit<\/code> receba um formato e, enquanto o usu\u00e1rio digita, o texto seja ajustado automaticamente.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Passos da implementa\u00e7\u00e3o<\/strong><\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Criamos um <strong>Class Helper<\/strong> para <code>TEdit<\/code>.<\/li>\n\n\n\n<li>Definimos um m\u00e9todo <code>FormatarTexto<\/code> que recebe uma m\u00e1scara (<code>R$ ###,###.00<\/code>, <code>(##) #####-####<\/code>, etc.).<\/li>\n\n\n\n<li>Aplicamos essa formata\u00e7\u00e3o <strong>no evento <code>OnTyping<\/code> ou <code>OnChange<\/code><\/strong>, garantindo que a m\u00e1scara seja aplicada em tempo real.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Implementa\u00e7\u00e3o do Class Helper<\/strong><\/h3>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \" >unit EditHelperUnit;\n\ninterface\n\nuses\n  System.SysUtils, System.Classes, FMX.Edit, System.Character;\n\ntype\n  TEditHelper = class helper for TEdit\n  private\n    function RemoverCaracteresNaoNumericos(const ATexto: string): string;\n    function AplicarMascara(const AMascara, ATexto: string): string;\n  public\n    procedure AplicarFormato(const AMascara: string);\n  end;\n\nimplementation\n\n{ Remove caracteres n\u00e3o num\u00e9ricos para facilitar a aplica\u00e7\u00e3o da m\u00e1scara }\nfunction TEditHelper.RemoverCaracteresNaoNumericos(const ATexto: string): string;\nvar\n  Ch: Char;\nbegin\n  Result := '';\n  for Ch in ATexto do\n    if Ch.IsDigit then\n      Result := Result + Ch;\nend;\n\n{ Aplica a m\u00e1scara ao texto digitado }\nfunction TEditHelper.AplicarMascara(const AMascara, ATexto: string): string;\nvar\n  i, j: Integer;\n  Resultado: string;\nbegin\n  Resultado := '';\n  i := 1;\n  j := 1;\n\n  while (i &lt;= Length(AMascara)) and (j &lt;= Length(ATexto)) do\n  begin\n    if AMascara[i] = '#' then\n    begin\n      Resultado := Resultado + ATexto[j];\n      Inc(j);\n    end\n    else\n      Resultado := Resultado + AMascara[i];\n\n    Inc(i);\n  end;\n\n  Result := Resultado;\nend;\n\n{ M\u00e9todo que pode ser chamado no OnChange ou OnTyping do TEdit }\nprocedure TEditHelper.AplicarFormato(const AMascara: string);\nvar\n  TextoFormatado: string;\nbegin\n  TextoFormatado := AplicarMascara(AMascara, RemoverCaracteresNaoNumericos(Self.Text));\n  Self.Text := TextoFormatado;\n\n  { Move o cursor para o final do texto }\n  Self.CaretPosition := Length(TextoFormatado);\nend;\n\nend.\n<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Como Usar no Formul\u00e1rio<\/strong><\/h2>\n\n\n\n<p>Agora podemos utilizar o <code>TEditHelper<\/code> em qualquer <code>TEdit<\/code>. No evento <code>OnTyping<\/code> ou <code>OnChange<\/code>, basta chamar <code>AplicarFormato<\/code>, passando a m\u00e1scara desejada.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Exemplo de Uso: Formatando como Moeda (<code>R$ ###,###.00<\/code>)<\/strong><\/h3>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \" >procedure TForm1.Edit1Typing(Sender: TObject);\nbegin\n  Edit1.AplicarFormato('R$ ###,###.00');\nend;\n<\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Exemplo de Uso: Formatando um Telefone (<code>(##) #####-####<\/code>)<\/strong><\/h3>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \" >procedure TForm1.EditTelefoneTyping(Sender: TObject);\nbegin\n  EditTelefone.AplicarFormato('(##) #####-####');\nend;\n<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Explica\u00e7\u00e3o do C\u00f3digo<\/strong><\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>RemoverCaracteresNaoNumericos<\/strong> \u2192 Remove qualquer caractere que n\u00e3o seja n\u00famero, para facilitar a aplica\u00e7\u00e3o da m\u00e1scara.<\/li>\n\n\n\n<li><strong>AplicarMascara<\/strong> \u2192 Percorre a string original e substitui os caracteres <code>#<\/code> pela entrada do usu\u00e1rio, preservando a formata\u00e7\u00e3o.<\/li>\n\n\n\n<li><strong>AplicarFormato<\/strong> \u2192 M\u00e9todo principal que pode ser chamado nos eventos <code>OnChange<\/code> ou <code>OnTyping<\/code> do <code>TEdit<\/code>.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Participe da Comunidade no Telegram<\/h3>\n\n\n\n<p>\ud83d\ude80 Quer continuar essa discuss\u00e3o e trocar ideias com outros desenvolvedores? Junte-se \u00e0 nossa comunidade no Telegram! L\u00e1, voc\u00ea pode comentar sobre o que achou deste artigo, tirar suas d\u00favidas e compartilhar suas experi\u00eancias com Delphi e ainda discutir ou tirar suas d\u00favidas sobre os mais variados temas em uma comunidade com mais de 1.000 desenvolvedores.<\/p>\n\n\n\n<p>\ud83d\udd17 <a href=\"https:\/\/t.me\/AdrianoSantosCommunity\" target=\"_blank\" rel=\"noreferrer noopener\">Clique aqui para entrar na comunidade<\/a><\/p>\n\n\n\n<p>Te vejo l\u00e1!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclus\u00e3o<\/strong><\/h2>\n\n\n\n<p>Os <strong>Class Helpers<\/strong> no Delphi s\u00e3o uma ferramenta poderosa para estender funcionalidades de classes existentes sem a necessidade de heran\u00e7a ou modifica\u00e7\u00f5es diretas no c\u00f3digo-fonte original. Eles s\u00e3o especialmente \u00fateis quando trabalhamos com bibliotecas fechadas ou quando queremos adicionar m\u00e9todos auxiliares para melhorar a reutiliza\u00e7\u00e3o e organiza\u00e7\u00e3o do c\u00f3digo.<\/p>\n\n\n\n<p>No exemplo pr\u00e1tico deste artigo, criamos um <strong>Class Helper para <code>TEdit<\/code><\/strong>, permitindo a formata\u00e7\u00e3o autom\u00e1tica de textos em tempo real, um recurso muito \u00fatil para aplica\u00e7\u00f5es mobile desenvolvidas com FireMonkey. Esse tipo de abordagem melhora a experi\u00eancia do usu\u00e1rio, garantindo que os dados sejam inseridos corretamente desde o momento da digita\u00e7\u00e3o.<\/p>\n\n\n\n<p>Apesar das vantagens, \u00e9 importante lembrar que o Delphi permite <strong>apenas um Class Helper ativo por classe por vez<\/strong>, o que pode ser uma limita\u00e7\u00e3o em projetos mais complexos. Ainda assim, se usados com planejamento, os <strong>Class Helpers<\/strong> s\u00e3o uma excelente alternativa para aprimorar a legibilidade, manutenibilidade e efici\u00eancia do c\u00f3digo.<\/p>\n\n\n\n<p>Se voc\u00ea gostou deste conte\u00fado, experimente aplicar <strong>Class Helpers<\/strong> em outras classes e descubra novas formas de otimizar seu desenvolvimento no Delphi! \ud83d\ude80\ud83d\ude0a<\/p>\n","protected":false},"excerpt":{"rendered":"<p>No Delphi, Class Helpers s\u00e3o um recurso \u00fatil para adicionar novos m\u00e9todos a uma classe j\u00e1 existente sem precisar modific\u00e1-la diretamente. Essa funcionalidade \u00e9 especialmente \u00fatil quando estamos trabalhando com classes de bibliotecas fechadas ou quando queremos estender funcionalidades sem alterar o c\u00f3digo original.<\/p>\n","protected":false},"author":1,"featured_media":995,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-992","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/992","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/comments?post=992"}],"version-history":[{"count":2,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/992\/revisions"}],"predecessor-version":[{"id":994,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/992\/revisions\/994"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/media\/995"}],"wp:attachment":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/media?parent=992"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/categories?post=992"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/tags?post=992"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}