Sie sind auf Seite 1von 5

Class Inseptors no Delphi: como adicionar propriedades a classes

existentes
Neste artigo veremos como adicionar variveis de escopo de classe (Fields)
dinamicamente a classes e componentes do Delphi utilizando Class Inseptors.
(2) (0)

Motivao
Quando h a necessidade de estender ou modificar o comportamento de classes e componentes no Delphi, existem algumas solues
possveis, desde as mais invasivas, como alterar o cdigo fonte original, at as mais orientadas a objetos, que fazem uso de herana e padres
de projeto. Uma soluo, propriamente desenvolvida para isso, o Class Helper. Ele permite obter esse resultado atravs de um cdigo
simples e organizado. Porm, por meio desse recurso s possvel trabalhar com mtodos e propriedades ligadas a esses mtodos,
inviabilizando a adio de atributos que estejam relacionados a variveis de escopo, conhecidas tambm por Fields (variveis que
normalmente so precedidas pelo sufixo F e armazenam dados para as propriedades).
Antes mesmo de surgir o recurso de Class Helper, no entanto, o compilador do Delphi j contava com outra soluo, conhecida como Class
Inseptor. Essa, de forma semelhante, permite inserir e modificar mtodos, bem como inserir novas variveis em uma classe para atender
necessidades especficas inerentes ao design do software.
Saiba mais sobre POO e Design Patterns no Delphi.

Problema: Adicionar variveis de escopo de classe com Class Helper


Embora essa limitao possa ser corrigida em verses futuras do Delphi, atualmente, quando se trabalha com Class Helper, o compilador
verifica para quais classes ele foi escrito e adiciona as propriedades e mtodos ao final dos j existentes na classe, ajustando os possveis
overrides. Como o compilador do Delphi exige que as variveis de escopo de classe (Fields) sejam declaradas obrigatoriamente antes das
properties, functions e procedures, caso elas sejam encontradas em um Class Helper, ser disparado um erro de compilao.
Na Listagem 1 apresentado um exemplo de Class Helper para um componente do tipo TButton, no qual necessrio realizar a contagem
dos cliques que foram efetuados sobre ele. Nesse cdigo, ento, realizamos uma tentativa de criar novas propriedades e sobrescrever o
mtodo Click.
01 unit UnitButtonCountHelper;
02
03 interface
04
05 uses
06 Vcl.StdCtrls;
07 type
08 TButtonCount = class helper for TButton
09 private
10

FLabelCount: TLabel;

11

FClickCount: integer;

12 public
13

property LabelCount: TLabel read FLabelCount write FLabelCount;

14

property ClickCount: integer read FClickCount;

15

procedure Click;override;

16 end;
17 implementation
18
19 { TButtonCount }
20
21 procedure TButtonCount.Click;
22 begin
23

Inc(FClickCount);

24
25 if assigned(FLabelCount) then
26

FLabelCount.Caption:=FClickCount.ToString;

27 inherited;
28
29 end;
30
31 end.
Listagem 1. Class Helper para um TButton que armazena a quantidade de cliques
Linhas 10 e 11: declaramos dois fields para armazenarem, respectivamente, um TLabel, que receber o valor do contador, e um integer, para armazenar a quantidade de cliques;
Linhas 13 e 14: declaramos as propriedades que apontam para as variveis FLabelCount e FClickCount, respectivamente;
Linha 15: sobrescrevemos o mtodo Click, j existente na classe TButon;
Linha 23: incrementamos o valor armazenado em FClickCount;
Linhas 25 e 26: verificamos se FLabelCount aponta para algum TLabel. Se verdadeiro, o Caption do TLabel recebe o valor contido em FClickCount.

Observao: O mtodo FClickCount.ToString, utilizado na linha 26, s possvel a partir do Delphi XE3. Em verses anteriores,
pode-se utilizar o IntToStr(FClickCount).
Ao executarmos o cdigo dessa listagem o compilador dispara um erro apontando para linha 10 com a seguinte mensagem:
[dcc32 Error] UnitButtonCountHelper.pas(10): E2599 Field definition not allowed in helper type

Isso indica que a definio Fields no permitida para um helper, invalidando totalmente seu uso para necessidades como a que foi
apresentada acima.
Saiba mais sobre Class Helpers no Delphi.

Soluo: Utilizando Class Inseptor


Embora no haja uma documentao oficial, Class Inspetor um recurso de compilador que injeta mtodos, propriedades e variveis em uma
superclasse atravs de uma classe especializada que contenha o mesmo nome.
O cdigo da Listagem 2 visa resolver o mesmo problema da Listagem 1, mas desta vez utilizando o recurso de Class Inspetor, com o qual
ser possvel armazenar a quantidade de cliques em uma varivel (field) dentro da instncia da classe, e ainda exibir esse valor em um
TLabel encapsulado por outra varivel.
01 unit UnitButtonCount;
02
03 interface
04
05 uses
06 Vcl.StdCtrls, SysUtils;
07
08 type
09 TButton = class(Vcl.StdCtrls.TButton)
10 private
11

FLabelCount: TLabel;

12

FClickCount: integer;

13 public
14

property LabelCount: TLabel read FLabelCount write FLabelCount;

15

property ClickCount: integer read FClickCount;

16

procedure Click; override;

17 end;
18
19 implementation
20
21 { TButton }
22
23 procedure TButton.Click;

24 begin
25
26 Inc(FClickCount);
27
28 if assigned(FLabelCount) then
29

FLabelCount.Caption:=FClickCount.ToString;

30 inherited;
31 end;
32
33 end.
Listagem 2. Exemplo de Class Inseptor para um TButton
Linha 9: criamos um tipo que possui o mesmo nome daquele j existente no Delphi, TButton, da unit Vcl.StdCtrls. Para o compilador no disparar um erro, necessrio, na
declarao da classe, colocar o caminho inteiro do tipo: Vcl.StdCtrls.TButton;

Linhas 11 e 12: declaramos as variveis que sero referenciadas pelas respectivas propriedades, nas linhas 14 e 15.

Aps a implementao desse cdigo, para cada unit do sistema em que for acrescentada a unit UnitButtonCount na clusula uses, todas as
instncias de TButton passaro a contar com as novas propriedades.
Assim, o compilador no ir disparar nenhum erro, pois a declarao dos fields encontra-se na posio adequada dentro da classe filha,
diferente do que acontece quando isso feito via Class Helper, em que eles so adicionados aps os mtodos j existentes na classe.
Para que isso funcione, no entanto, h uma nica exigncia: sempre manter a declarao da unit onde foi criado o Class Inseptor
(UnitButtonCount, neste caso) aps a declarao da unit do componente original (Vcl.StdCtrls, neste exemplo), da seguinte forma:
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, UnitButtonCount;

Vcl.Controls,

Feito isso, para utilizar esse novo boto, basta atribuir um label sua propriedade LabelCount dentro do evento OnCreate do form em
que o label ser atualizado com um novo valor a cada click do mouse, conforme o cdigo a seguir:
procedure TForm3.FormCreate(Sender: TObject);
begin
Button1.LabelCount:=Label1;
end;

Do mesmo modo que acessamos a propriedade anterior, tambm ser possvel acessar a propriedade ClickCount desse boto, ou qualquer
outra que tenhamos adicionado por meio de Class Inseptors. No caso do nosso exemplo, basta declarar: Button1.ClickCount.

Publicado no Canal .net

por Hlio Carlos

Guru .net e tecnologias MS

Das könnte Ihnen auch gefallen