Delphi - Segredos e Solues

CAPTULO 6
 
Objetos

Neste ponto, voc provavelmente j est bem  vontade com as tcnicas
bsicas para manusear objetos internos do Delphi. Para ir mais longe com
O Delphi, porm, voc  precisa conhecer alguma coisa a respeito da
implementao de programas orientados a objetos do Delphi. A programao
orientada a objetos (POO) parece ser o modelo  de programao dominante
nos dias de hoje, depois de substituir as tcnicas da programao
"estruturada" desenvolvidas no incio da dcada de 70. Se voc no
trabalhou  com objetos antes, provavelmente estar imaginando o que
significa todo esse rebolio. Este captulo foi concebido para lhe
mostrar isso (bem, pelo menos para lhe  dar uma idia). J que h uma
vasta terminologia necessria para que a POO tenha algum sentido, vamos
comear com alguns conceitos e definies. Depois disto, vamos  lhe
mostrar os fundamentos de como o Delphi implementa a POO.

        Devemos observar, porm, que  possvel falar indefinidamente a
respeito da programao orientada a objetos. Uma reviso rpida de Books
In Print mostra  que h mais de 150 livros a respeito da programao
orientada a objetos, e parece que a cada  no Delphi exigiria um livro
pelo menos do porte deste - ou provavelmente muito maior. Neste captulo
ns pretendemos apenas apresentar voc a POO. Em particular,  ns no
discutimos como construir seus prprios componentes visuais no Delphi.
Para isso, favor se referir ao Component Writer's Guide fornecido com o
Delphi (que,  no podemos evitar de destacar, tem mais ou menos a metade
do tamanho deste livro e , infelizmente, bastante resumido apesar de
tudo). Voc tambm pode querer comprar  o cdigo fonte, para os
componentes do prprio Delphi, caso ele no esteja includo em sua
prpria verso do Delphi. Ele  vendido por um preo bem razovel pela
Borland.


Comeando

Vamos comear com uma pergunta que, aparentemente, parece no ter nada a
ver com programao: "Como  que a Gateway 2000 tornou-se uma empresa de
dois bilhes de  dlares mais rapidamente do que qualquer outra empresa
na histria americana?". A maioria das pessoas provavelmente diria que
eles fazem bons computadores e os vendem  a preo de banana. Mas no
pare a: "Como fizeram isso?". Bem, grande parte da resposta  que eles
contrataram grande parte do trabalho. Eles compraram componentes  de
fornecedores com reputao e depois os montaram. No investiram dinheiro
algum no projeto e construo de fontes de alimentao, drives de disco,
placas-mes  etc. Isso possibilitou a eles ter um bom produto a um preo
baixo.
       Pergunte a si mesmo por um momento como isso pode funcionar. A
resposta bvia (e at um certo ponto correta)  que o que eles estavam
comprando era "funcionalidade  pr-embalada". Por exemplo, quando
compravam uma fonte de alimentao, estavam comp (sada de alimentao
regular, potncia disponvel e assim por diante.) A programao
orientada a objetos resulta da mesma idia. O seu programa  formado por
objetos  com certas propriedades e funes. Voc depende dos objetos
para no interagir de forma no-documentada com outros objetos ou cdigo
em seu projeto. Quer voc construa  o objeto ou o compre, poder
depender da situao de sua carteira ou quanto tempo voc tem livre. Em
qualquer um dos casos, desde que os objetos satisfaam as suas
especificaes, voc no se preocupa muito em saber como a
funcionalidade foi implementada. Na POO, voc se preocupa  com aquilo
que o objeto apresenta.
       Assim, da mesma forma que a Gateway no se preocupa com o que h
dentro de uma fonte de alimentao desde que ela faa o que eles querem,
a maioria dos programadores  no precisa se preocupar em como os botes
de comando so implementados no Delphi os objetos do Delphi fazem o que
voc espera que faam!
        O segredo para a melhor produtividade possvel na programao
orientada a objetos  tornar seus objetos o mais completo possvel e, da
melhor forma possvel,  fazer com que os outros objetos e partes de seu
programa informem aos objetos o que faze a objetos  fazer os clientes
enviarem mensagens aos objetos. Ao projetar seus objetos para tratar
todas as mensagens apropriadas e manipular seus dados internamente,
voc maximiza a reutilizao e minimiza o tempo da depurao.
       Com essa caracterstica, voc viu uma evidncia bastante clara de
que os objetos internos do Delphi se enquadram bem nesse paradigma. Eles
so muito ricos  em funcionalidade.  evidente que, ocasionalmente, voc
pode ser obrigado a acrescentar seus voc mesmo. Falando no geral,
raramente vale a pena reinventar a roda. Se voc gasta 40 horas para
construir um componente e pode compr-lo por $200, devemos perguntar:
"Isso realmente vale a pena?". Fornecedores como MicroHelp produzem
produtos de qualidade que valem o custo (normalmente) pequeno. Ns
sempre utilizamos produtos  comerciais em nossos aplicativos e, em
geral, ficamos satisfeitos com os resultados (especialmente se o
cdigo-fonte foi fornecido para que ns, caso haja necessidade,
pudssemos configurar ainda mais o componente).
       Entretanto, se voc tem de escrever seus prprios objetos, um
outro princpio da POO torna isso tambm mais fcil: objetos podem ser
construdos sobre outros  objetos. Quando voc faz isso, o objeto novo
comea por herdar todas as propriedades e fu qualquer propriedade ou
funo do pai. Dadas a funcionalidade interna do Delphi e as ferramentas
de terceiros disponveis, suspeitamos que voc quase nunca precisa
construir um novo componente visual. O que encontramos em nossa
programao  que a maioria dos objetos que criamos  no-visual. Por
exemplo, criar um objeto StringGrande  que acrescenta funes string ao
Delphi para manipular strings grandes  uma coisa evidente para se
fazer. Ns utilizamos isso bastante e valeu o tempo necessrio  para
constru-lo. (Na verdade, a Borland deveria t-lo feito - eles dizem que
o faro para o prximo lanamento. )

O Vocabulrio da POO

A programao estruturada tradicional consiste em projetar as estruturas
de dados e depois manuse-las com funes em maneiras especficas que
terminam, teoricamente,  com certeza. (Estas, em geral, so chamadas
algoritmos.)  por isso que o projetista do Pascal original, Niklaus
Wirth, chamou seu famoso livro de programao Algorithms  + Data
Structures = Programs (Prentice Hall, 1976). Observe que no ttulo de
Wirth o algoritmo vem primeiro e as estruturas de dados vm depois. Isso
imitava a maneira  como os programadores trabalhavam naquela poca.
Primeiro, voc decidiu como manusear os dados, depois decidiu qual
estrutura impor aos dados para facilitar a manipulao.  A POO coloca
tanto os algoritmos como as estruturas de dados no mesmo nvel.
       O restante desta seo explica a terminologia bsica da POO. H
uma grande quantidade dela mas vale a pena aprender por dois motivos. O
primeiro  que voc  precisar de parte dessa terminologia para
compreender as discusses neste captulo; o segu ler Component Writer's
Guide, ou ir mais alm com a POO.


Classes

Em geral, uma classe  descrita como o modelo ou projeto a partir de
onde o objeto realmente  feito. A maneira padro para pensar a respeito
de classes  pensar  nelas como o cortador de doces, e o objeto em si
como o doce. A "massa" na frma de memria algumas vezes tambm tem de
ser alocada. O Delphi  muito bom em esconder  esse passo de "preparao
da massa" de voc. Ao criar um objeto de uma classe,  dito que voc
criou uma instncia da classe.

Encapsulamento

Esse  o conceito-chave ao trabalhar com objetos. Formalmente,
encapsulamento no era mais nada do que combinar os dados e o
comportamento em um pacote. Algumas  pessoas gostam de pensar em um
objeto como um tipo especial (veja o Captulo 5) que no tem apenas
dados mas tambm funes e procedimentos como parte dele. Esse  tipo
novo corresponde  classe do objeto e essa , de fato, a sintaxe
utilizada pelo Delphi para criar objetos (veja "Criando um Objeto no
Delphi" mais adiante,  neste captulo).

NOTA: Os dados em um objeto normalmente so chamados de suas variveis
de instncia ou campos, e as funes e procedimentos so seus mtodos.

        Uma regra fundamental em fazer o encapsulamento funcionar  que
os programas nunca (bem, quase nunca) deveriam acessar diretamente as
(os campos) variveis  de instncia em um objeto. Os programas deveriam
interagir com esses dados apenas por meio a dar a voc uma maneira para
interagir com as variveis de instncia sem violar o encapsulamento.) O
encapsulamento  a maneira de dar ao objeto seu comportamento  do tipo
"caixa-preta", que  a chave para a eficincia de reutilizao e
depurao.

Herana

Herana  a possibilidade de fazer classes que descendem de outras
classes. O objetivo da herana  tornar mais fcil a construo de um
cdigo para tarefas especializadas.  As variveis de instncia e os
mtodos do descendente (algumas vezes chamadas de subclasses) comeam
sendo os mesmos. Isso  eficaz para os projetistas da linguagem:  eles
tm sempre uma base onde construir classes novas. Por exemplo, os
projetistas do Delphi comearam com uma caixa de edio bastante geral
de onde constroem caixas  de edio mascaradas e caixas de edio
normais. De forma ainda mais genrica, todos os objetos no Delphi
descendem de uma nica classe chamada, naturalmente, de  TObject. (A
propsito, T  abreviao de Type. )
       As classes de onde os outros objetos so originados algumas vezes
so chamadas de classes-mes ou classes de base.
       A herana tambm  eficaz ao programador final. Por exemplo, o
aprendizado do Delphi seria muito mais difcil se as propriedades como
Left e Top funcionassem  de forma diferente para os componentes
diferentes. Uma vez que todos os componentes visv Uma vez que no havia
necessidade dos projetistas do Delphi redefinirem como Left e Top
funcionam em outros componentes, eles se comportam da mesma forma para
todos  os componentes.
       Um outro motivo da eficincia torna-se aparente quando voc
inicia a construo de seus prprios componentes. Se precisar construir
uma caixa de edio personalizada,  pode comear com a me de todas as
caixas de edio ou com um de seus filhos. Ao j foi feito para voc. A
coletnea de classes de base e de subclasses  chamada de hierarquia de
classe. As hierarquias de classe so muito parecidas com a classificao
das espcies que voc aprendeu em Biologia: vertebrados representam um
dos subconjuntos dos cordados; e aves, mamferos e rpteis, anfbios e
peixes so subconjuntos  dos vertebrados. O Delphi tem a sua prpria
hierarquia de objetos, conforme mostrado na Figura 6.1. Algumas vezes
pode ser til conhecer isso. Para mais informaes  sobre hierarquia de
classes no Delphi veja a seo a respeito do ObjectBrowser a seguir.

 1 - TObject
   2 - Exception 3 - TStream 4 - TPersistant 5 - Tprinter 6 - TList


                7-TgraphicsObject 8-Tcraphic 9-Tcomponent 10-Tcanvas
11-Tpicture 12 -TStrings


               

                                             13 - TControl 


               
   
 14 - TgraficControl 15 - TWinControl



Figura 6.1 Uma verso simplificada da hierarquia de objetos da
Biblioteca de Componentes Visuais do Delphi (VCL).

        Normalmente as subclasses utilizaro (herdaro) os mesmos
mtodos que a classe-me. A POO (e o Delphi) permite-lhe definir um
mtodo novo em uma subclasse  mas com o mesmo nome. A isso chamamos de
redefinio. Uma linguagem realmente orientada a o mtodo para at
aquilo que normalmente  chamado de polimorfismo. A idia que h por
detrs do polimorfismo  que embora a mensagem possa ser a mesma, o
objeto determina  como responder. Polimorfismo pode ser aplicado a
qualquer mtodo herdado de uma classe de base.
        O polimorfismo  vital porque facilita o trabalho de um
programador. Por exemplo, quando voc define um objeto novo baseado em
um objeto existente, voc  no gostaria de reconstruir o cdigo da me
para levar em conta a existncia de um objeto nov param de crescer! )
        O segredo para fazer o polimorfismo funcionar  chamado de
vinculao tardia. Isso significa que o compilador no gera o cdigo
para chamar um mtodo durante  a compilao.
        Em vez disso, todas as vezes em que voc utiliza um mtodo com
um objeto, o compilador gera um cdigo que lhe permite calcular que
mtodo chamar utilizando  informao de ponteiro includa ao objeto que
o chamou. Os mtodos que permitem vinculao .EXE mas esto apenas
potencialmente l.

Criando um Objeto no Delphi

Vamos comear imaginando que queremos fornecer um kit de ferramentas aos
projetistas dos jogos de cartas gerados por computador. Evidentemente
que precisamos de  um objeto que tome o lugar de um baralho. Para que
no fiquemos atolados em uma srie de detalhes, vamos tornar isso um
objeto no-visual. Como uma primeira aproximao  (a construo de
objetos tambm se beneficiados refinamentos graduais que voc
provavelmente utilizou antes do desenvolvimento de programas), decidimos
que esse  objeto ter dados (uma varivel de instncia) consistindo de
um vetor de string de 52 entradas para as cartas, e dois procedimentos e
uma funo para seus mtodos.  Um procedimento inicializaria as cartas,
um segundo os embaralharia, e a funo distribuiria as cartas.
        O cdigo para a criao desse objeto no-visual poder ser
assim:

        type
            Baralho = class(Tobject);
            carto: array [1..52] of String;
            procedure Inicializa;
            procedure Embaralha; 
            function Distribuir(NumeroCarta: Integer): String;
        end;

NOTA: Quando voc define um novo objeto Delphi, a definio  colocada
embaixo da declarao de tipo onde o prprio formulrio foi declarado. 

        Vamos ver mais de perto essa declarao de objeto. Conforme
mencionado antes, falando de forma resumida, uma declarao de objeto se
parece com uma declarao  de tipo e ocorre depois da declarao do
formulrio. Observe, porm, que a primeira lin (Tobject) utilizando a
sintaxe:

        NomeObjeto = class(Tobject);

DICA DE PASCAL: Embora o Delphi suporte a palavra-chave Object para a
criao de objetos, voc comea melhor utilizando a sintaxe acima para
descender de Tobject.  Entre as outras vantagens dessa descendncia est
aquela em que voc no precisa se preocupar a respeito das operaes
Constructor/Destructor, uma vez que so parte  de Tobject.

        Em seguida, temos a declarao dos dados (as variveis de
instncia ou campos) e depois vm as declaraes para os mtodos
(funes e procedimentos) para  esse objeto. Se realmente quisssemos
implementar esse objeto, teramos que escrever o cdig
        Ns pensamos um pouco mais sobre o objeto Baralho e decidimos
que seria melhor fazer com que as cartas individuais fossem elas mesmas
objetos. Dessa forma,  poderamos melhorar a definio delas ainda mais
(possivelmente incluir um componente visu campo de instncia em um novo
objeto Baralho. (Os objetos podem ter outros objetos como campos de
instncia.) Refinamos ainda mais o modelo permitindo dois procedimentos
e uma funo para estes mtodos. Um procedimento inicializaria as
cartas, um segundo embaralharia, e a funo distribuiria uma carta.
       

O cdigo para criar esse objeto no-visual poderia ser assim:
        type
           Carta = class(TObject);
             public {utilizado para mtodos que deveriam ser acessveis
fora da unidade}
              procedure Atribuir(Value: Byte);
              function Nome: String;
             private {utilizado para mtodos que no deveriam ser
geralmente acessveis)
              OValor: Byte;
       end;
       Baralho = class(TObject);
         public
            procedure Inicializa;
            procedure Embaralha;
            function Distribuir: Carta;
         private
            Cartas: array (1..52] of Carta;
            Cont: Byte;
       end;

        Observe que esse objeto mais sofisticado inclui as
palavras-chave opcionais private e public para definir duas sees. O
que  declarado na seo private  no ser visvel a outras unidades;
qualquer coisa declarada na seo public estar disponv acessar um
objeto da mesma unidade, no h diferena entre pblico e privado.) A
sintaxe para utilizar dados ou mtodos declarados publicamente envolve
apenas o  fornecimento do nome do objeto ou do formulrio. A sintaxe
geral para acessar um mtodo pblico de uma outra unidade utiliza um
ponto para identificar a unidade.  Um exemplo disso  assim:
        NomeDa Un idade. NomeDoOb jeto. NomeDoMetodoPublico
       
        Uma rea normalmente confusa ao tratar com objetos  decidir
sobre os parmetros que devem ser utilizados para seus mtodos. Por
exemplo, voc pode ter esperado  que a funo inicializada recebesse um
parmetro Cartas. No  esse o caso e resultar aos mtodos de um objeto
inclui implicitamente um parmetro para o prprio objeto. Portanto, ao
implementar o mtodo, voc poder acessar os parmetros de instncia
diretamente.
        Voc realmente escreve as funes e procedimentos que fornecem
os mtodos na parte implementation da unidade onde o objeto  definido.
O cdigo de nosso  exemplo poder ser assim:
         procedure Baralho.lnicializa;
           var
          I: Byte;
          C: Carta;
        begin
          for I :=1 to 52 do
             begin
               C := Carta.Create;
               C.AtribuirI);
               Cartas(I] := C;
             end
          Cont := 52;
        end;

        Observe que a sintaxe para definir um mtodo imita a do prprio
Delphi: voc utiliza um ponto entre o nome do objeto e o nome do mtodo.
Observe tambm que  esse mtodo tem acesso s variveis (campos) de
instncia do baralho sem a necessidade de 
        Definir o tipo de objeto e seus mtodos no  suficiente. Para
utilizar o objeto, voc tem de dizer ao Delphi para cri-lo (em POO,
isso normalmente  chamado  de instanciando um objeto por uma chamada de
construtor). Como sempre, primeiro voc te
       
 var
           Poquer: Baralho;

A sintaxe para criar o nosso exemplo ficaria assim em nosso cdigo:
         Poquer := BaraIho.Create;

        O mtodo Create do Delphi  quem diz ao Delphi para reservar
memria para seu objeto. (Os objetos no Delphi so na verdade
ponteiros.) Por esse motivo, voc  tem que ter certeza de liberar a
memria assim que terminar com seu objeto. Voc faz isso
       
        Poquer. Free;

        Isso normalmente  nomeado de chamada destrutiva.

NOTA: Na prtica, voc tem de ter a certeza de que o Delphi processa o
mtodo Free. Voc faz isso colocando os mtodos Create/Free em um bloco
try/finally conforme  descrito no Captulo 7.
 
Objetos da Visual Component Library (Biblioteca de Componentes Visuais)

Se voc deu uma olhada em uma unidade antes e depois de ter acrescentado
componentes novos, provavelmente observou as mudanas dramticas feitas
pelo Delphi no cdigo.  A maioria dessas mudanas ocorre quando voc
cria novos objetos Delphi a partir da Biblioteca de Componentes Visuais
- ou VCL, como normalmente  chamada.
        Vale a pena ver um pouco mais de perto o cdigo acrescentado a
uma unidade quando voc acrescenta componentes. Assim, inicie um projeto
novo e visualize  a unidade dele. Observe que as linhas logo abaixo da
clusula uses na seo interface de um f

        type
        TForml = class(TForml;

                Eis o que est acontecendo nos bastidores:

        *Ao utilizarmos a palavra-chave class sabemos que o Delphi est
criando um objeto novo derivado do tipo de objeto TForm.
        *J que a declarao do objeto se encontra na seo interface,
outras unidades podem ter acesso a esse objeto.

        Em seguida, voc v as linhas que so assim:
    
         var
             Form1: TForm1;

        Isso indica que o Delphi est declarando uma nova varivel do
tipo TForm 1.
        Em seguida, acrescente um componente, digamos, um boto de
comando, a esse formulrio. A declarao de tipo embaixo da clusula
uses muda agora para:
        
        type
         TForm1= classITForm);
           Button1: TButton;

        Observe que o Delphi acrescentou automaticamente uma varivel de
instncia (campo) Button 1 ao objeto TForm 1. Finalmente, acrescente um
procedimento de  evento clique ao seu formulrio. A clusula type muda
para:
       
         type
             TForm1 = class(TForm);
             Button1: TButton;
             procedure ButtonlClick(Sender: TObject);

        Se tudo isso est comeando a se parecer com a definio do
objeto Baralho, voc no est tendo vises. Um ponto chave em trabalhar
com o Delphi  perceber  que o que o Delphi est realmente fazendo 
facilitar para voc a criao de objetos visua seu formulrio  ele
mesmo um objeto Delphi. Mais precisamente, esse cdigo mostra que o
Delphi escreveu para voc o cdigo que  necessrio para criar um novo
objeto  visual (em nosso caso, uma janela com um boto). E,
evidentemente, os objetos Delphi tm como herana da VCL uma quantidade
incrvel de funcionalidade! (Um dos benefcios  adicionais ao deixar que
o Delphi crie as declaraes  que ele realiza qualquer mudana
necessria  medida que voc acrescenta ou remove componentes.
        O Delphi tambm cuida da alocao de memria para os componentes
da VCL. Normalmente, voc no precisa se preocupar sobre liberao de
memria para os objetos  criados a partir da Biblioteca de Componentes
Visuais.)

NOTA: Assegure-se de que voc no colocar as definies de seus
prprios objetos no comando de tipo que o Delphi mantm para o
formulrio. Essa informao  salva  no arquivo de formulrio (.DFM) e
quaisquer mudanas dificultaro (algumas vezes impossibilitando) ao
Delphi a criao do formulrio.

        

As Regies Pblicas e Privadas de uma Declarao de Formulrio

Se voc olhar mais um pouco os comandos de tipo que definem um
formulrio quando voc o utiliza pela primeira vez, ver que h sete
linhas como essas:
                    
                type
                      TForml = class(TForm);
                      private
                         {Declaraes privadas}
                      public
                         {Declaraes pblicas}
                   end;

        Como com os objetos que voc cria, a diferena principal  que
quaisquer dados ou mtodos declarados na seo private no sero
visveis a outras unidades,  e qualquer coisa declarada na seo public
estar disponvel a outras unidades. (Isso sign no h diferena entre
public e private.) A sintaxe para utilizar dados ou mtodos declarados
publicamente tambm envolve apenas o fornecimento do nome do formulrio.
A sintaxe geral para acessar um mtodo pblico de um outro formulrio
utiliza um ponto,
                   
        NomeDoModelo. NomeDoMetodoPublico

O Parmetro Sender

A esta altura voc j reparou que todos os procedimentos de eventos
utilizam um parmetro Sender do tipo TObject. Uma vez que TObject  o
ponto de partida para todos  os objetos na Biblioteca de Componentes
Visuais, o parmetro Sender, quando utilizado corretamente, pode
proporcionar a seu cdigo uma incrvel flexibilidade. O  que o parmetro
Sender faz  deixar voc saber qual o componente que acionou o evento.
Isso facilita a utilizao do mesmo procedimento de evento para dois
componentes  diferentes. Por exemplo, vamos supor que voc queira que um
boto e um item de menu faam a mesma coisa. Seria, bobagem ter que
escrever o mesmo procedimento de  evento duas vezes. Os passos
necessrios para compartilhar um procedimento de evento so relacionados
a seguir.
       
        1. Escreva o procedimento de evento para o primeiro objeto.
        2. Selecione o objeto ou objetos novos.
        3. V at a pgina Event no Object Inspector
        4. D um clique na seta para baixo que aparece na coluna da
direita do evento que voc quer compartilhar. (O Delphi vai lhe fornecer
uma lista com todos  os procedimentos de evento compatveis que existem
no formulrio. )
        5. Selecione o evento da lista suspensa.

        Isso  tudo o que voc precisa fazer. Agora, o Delphi vai chamar
o procedimento de evento compartilhado sempre que o evento ocorrer em
qualquer um dos componentes  compartilhados. (Voc tambm pode
selecionar os componentes primeiro e escrever mai
        Evidentemente que voc precisa ter uma maneira para distinguir
qual o componente que chamou o procedimento de evento compartilhado.
Voc faz isso analisando  o parmetro Sender pelo cdigo. Por exemplo, 
possvel ter um cdigo como este:

        begin
         if Sender = Button1 then
          {cdigo do boto 1  colocado aqui)
         else
           if Sender = Button2 then
              (cdigo do boto 2  colocado aqui};
         end;

        Em geral, voc verifica se o parmetro Sender  igual ao nome do
componente.


Variveis de Objeto

Uma varivel de objeto  simplesmente uma
varivel################################################
#################################################

######################################################
######################################################
###########################

######################################################
###################################################
###########################

################## no Delphi que  declarada como sendo de um tipo
correspondente a um objeto Delphi. Por exemplo:
        
        var
          Form:TForm;
          UrnaCaixaDeEdicao: TEdit;
        VetorDeCaixaDeEdicao: arrayf1..101 of TEdit;

        Observe que podemos criar vetores de objetos Delphi (voc pode
at utiliz-los em registros).
       As variveis de objeto so utilizadas constantemente em projetos
Delphi mais sofisticados. Por exemplo, quando voc comea a compartilhar
procedimentos de  eventos, ter que verificar que tipo de objeto  o
parmetro Sender.  uma caixa de edio,  que tipo de objeto  o
parmetro Sender utilizando a palavra-chave is com uma varivel de
objeto.
        Por exemplo, faa uma caixa de edio, denominada Edit 1, e um
rtulo, denominado Label 1, compartilhe o procedimento de evento clique
do componente Edit  1. Em seguida tente o seguinte cdigo:
       
         procedure TForm1.Edit1Click(Sender: Tobject);
           if Sender is TEdit then
             Edit1.Text :='Clique dado na caixa de edio'
          else
             LabeI1.Caption =: 'Clique dado no rtulo';
          end;
        end;

        Em geral, voc verifica se Sender  um TEdit, TCommand, TLabel,
ou algum outro componente utilizando, evidentemente, a palavra-chave is.
        Entretanto, uma vez que o parmetro Sender  do tipo TObject,
voc no pode testar diretamente a existncia de coisas como a
propriedade Name do componente.  Uma declarao como Sender.Name no faz
sentido porque classe TObject no tem uma proprie fazer  normalmente
chamado de moldar um objeto de um tipo em um outro tipo. Evidentemente,
voc no pode moldar um objeto em outro objeto incompatvel. Voc no
pode, por exemplo, transformar uma caixa de edio em um componente
Memo.
        Para moldar um objeto no Delphi, utilize o nome de classe como
uma funo e a varivel de objeto (normalmente do tipo TObject) como o
parmetro. Por exemplo,  vamos supor que voc tenha um grupo de caixas
de edio que compartilham um procedimento est vazia dentro do
procedimento de evento compartilhado.
       
         procedure TForm1.EditlClick(Sender: Tobject);
            var
             EditBox: TEdit;
            begin
             EditBox := TEdit(Sender);
             if EditBox.Text = " then ShowMessage('EditBox.Name');
           end;
           end.

        Da mesma forma que os procedimentos de evento tomam objetos como
parmetros, voc pode escrever seus prprios subprogramas que utilizam
variveis de objeto  como um ou mais dos parmetros. Por exemplo, se
voc quisesse escrever um procedimento que poderia utilizar o cdigo que
segue.
        
        procedure TextoCaixaAlta(EditBox: TEdit);
         begin
          EditBox.Text = UpperCase(EditBox.Text);
        end;

        Como outro exemplo da utilizao de variveis objeto, vamos
supor que voc precise escrever um cdigo que se repete em todos os
componentes em um formulrio,  que encontra as caixas de edio, e que
depois deixa em branco a informao em cada caix e Component.Count do
formulrio. Essas propriedades permitem-lhe acessar os componentes em um
formulrio. Eis um exemplo do cdigo que voc pode utilizar:
        procedure LimparCaixa/NomeForm: Tform); var
          i: Integer;
        begin
          for i :=1 to NomeForm.ComponentCount -1 do
              if NomeForm.Components[i] is TEdit then
                NomeForm.Components[i].Text =  ;
        end;

NOTA: O Delphi tambm tem uma propriedade Controls. A diferena  que a
propriedade Components de um objeto lhe fornece uma lista de componentes
pertencentes aos  objetos, enquanto a propriedade Controls lhe fornece
uma lista com todos os componentes que so janelas-filhas do objeto.
Isto se torna importante quando voc utiliza  um componente continente
como uma caixa de grupo. Os componentes em uma caixa de grupo continuam
pertencentes ao formulrio e, dessa forma, esto relacionados na
propriedade Components do formulrio. So entretanto, janelas-filhas da
caixa de grupo e, assim, no esto relacionadas na propriedade Forms
Controls, mas, sim,  na propriedade Controls da caixa de grupo.

Criando Objetos Delphi em Tempo de Execuo

 bastante comum ter de criar novos objetos Delphi durante a execuo.
Voc pode precisar de uma nova lista de strings, por exemplo, para
armazenar dados, ou pode  descobrir que precisa colocar uma nova caixa
de edio em um formulrio em resposta a uma situao especial. Voc
pode at mesmo ter de criar um formulrio novo.  (Voc poderia,
evidentemente, criar a caixa de edio ou o formulrio durante o projeto
e depois escond-lo at que seja necessrio. Entretanto, isso no s
desperdia  memria mas, se voc o fizer com muita freqncia, faz com
que o seu projeto fique mais lento e exija muito mais dos recursos
limitados do Windows.)
        Suponha, por exemplo, que voc quer criar uma nova lista de
strings durante a execuo. Qualquer lista de strings tem de ser
derivada do objeto TString do  Delphi. Eis um exemplo do cdigo que voc
precisa:
        
        var
          MinhaListaSTR: TStrings;
        begin
          MinhaListaSTR := TStringList.Create;
        try
          {cdigo para a lista de strings}
        finally
          MinhaListaSTR.Free;
        end;

        (TStringList  uma descendente de TStrings que  utilizada
quando voc precisa manter a lista.)

NOTA: Como com qualquer objeto que voc cria,  preciso liberar a
memria utilizando um bloco try/6nally conforme indicado na listagem
precedente. Veja o Captulo  7 para saber mais a respeito dessas
tcnicas.

        Ocasionalmente, voc vai precisar de uma lista de strings que
est disponvel durante todo o tempo em que o aplicativo est sendo
processado. Para isso:
       
        1. Declare um tipo de campo TString na declarao do formulrio
        2. Crie a lista de strings no manipulador de eventos OnCreate do
formulrio.

NOTA: Esteja certo de liberar a memria que voc alocou para qualquer
lista de strings de longa durao. O procedimento de evento OnDestroy 
o lugar mais comum  para fazer isso.




Criando Novos Objetos Visuais em Tempo de Execuo

Vamos supor que voc queira criar uma caixa de edio durante a
execuo. Um exemplo do cdigo necessrio  algo assim:
        
        var
              NewEditBox: TEdit;
          begin
          NewEditBox := TEdit.Create (Self);
          NewEditBox.Parent := Form1;
          {neste ponto, o componente existe de modo que voc deveria
especificar propriedades como Left, Top, Visible! e assim por diante}
        end;

        O que segue so discusses rpidas sobre os mtodos e
palavras-chave utilizadas nesse exemplo.

Self

Todo componente que voc cria tem de pertencer a um outro componente. A
sintaxe geral do mtodo Create reflete isso:
       
        Create(AOwner: TComponent)
       
        Na maioria das vezes, voc utiliza a palavra-chave self,
significando que o componente pertence ele prprio. Isso torna seu
cdigo responsvel para dispor  dele. Por outro lado, se voc torna um
outro componente o proprietrio de seu componente no objeto quando ele 
destrudo.

NOTA: Da mesma forma que com objetos no-visuais, esteja certo de
liberar a memria utilizada pelos seus objetos caso eles pertenam a si
prprios. (Utilize o mtodo  Free, conforme j descrito neste captulo.)

Mtodo-Pai

Cada componente utilizado em janela tem de ter um pai antes que voc
possa especificar as suas propriedades. O componente pai  o componente
que contm o componente  novo - no  necessariamente o proprietrio do
componente novo. Normalmente, o pai de um componente novo  o
formulrio, mas pode ser um painel ou uma caixa de grupo  (ou qualquer
controle que possa conter um outro). Embora menos comum, utilizando a
palavra-chave self, voc pode fazer com que o pai de um componente seja
ele mesmo.  Voc utiliza o mtodo Parent para atribuir o pai a um
componente.

DICA VISUAL BASIC: Se voc tem de criar uma estrutura parecida a uma
matriz de controle Visual Basic, declare uma matriz de variveis objeto
e depois utilize as  tcnicas descritas acima para cri-las
individualmente.

O ObjectBrowser

De vez em quando,  til ver diretamente a hierarquia dos objetos
Delphi. Isso  feito por meio do ObjectBrowser que est disponvel pela
escolha de View(Browser.  O ObjectBrowser pode fazer muito mais do que
olhar para a hierarquia do objeto. Ele pode ajud-lo a analisar as
unidades e variveis globais em seu cdigo. Ele lhe  permite at mesmo
se movimentar rapidamente para coisas como as declaraes de cdigo para
as variveis globais. O ObjectBrowser  mostrado na Figura 6.2.

NOTA: Voc tem de ter compilado seu programa pelo menos uma vez para
poder utilizar o ObjectBrowser. Entretanto, no precisa estar no modo
break para operar com  ele.

NOTA: Como a maioria dos objetos Delphi, o ObjectBrowser tambm tem um
SpeedMenu que lhe permite acessar as partes mais comuns do browser.

        Uma vez que o ObjectBrowser  a porta para todo o funcionamento
interno de Delphi,  muito fcil ser sobrecarregado pela informao
apresentada. Apenas ocasionalmente  voc precisa trabalhar com o browser
e, quando o fizer, vai querer filtrar info ou apenas nas constantes em
um objeto. Os filtros so controlados pelos cones que aparecem na barra
Show no topo do ObjectBrowser. Voc pode utilizar trs mtodos
diferentes para especificar um filtro:

        *D um clique no boto associado do filtro. (O boto C, por
exemplo,  para as constantes; o boto P  para Functions e Procedures.)
        *Selecione (ou cancele a seleo de) o filtro de smbolo da
pgina Browser da caixa de dilogo Environment Options trabalhando com
as caixas de escolha dessa  pgina.
        *Pressione a simplificao de teclado para o filtro.

DICA: Se na maioria ds vezes voc utiliza o ObjectBrowser para olhar um
tipo de objeto, utilize a pgina Browser na caixa de dilogo Environment
Options para tornar  aquele o padro.

        Como voc pode ver na Figura 6.2, o ObjectBrowser  dividido em
dois painis (redimensionveis). O da esquerda  chamado de painel
Inspector e o da direita  de painel Details. Ao utilizar o ObjectBrowser
pela primeira vez, o Delphi faz com que voc para mudar aquilo que voc
est folheando  utilizar a SpeedMenu para o browser. Dar um clique no
item apropriado no Speed-Menu permite-lhe folhear no apenas os  objetos
mas tambm as unidades, informaes globais, ou de smbolos em seu
projeto.

DICA: O ObjectBrowser tem um recurso de procura hbil que funciona de
forma incremental. Isso facilita a movimentao pelo ObjectBrowser. 
medida que voc coloca  caracteres, o ObjectBrowser vai at o smbolo
que combina com o texto que voc digitou, e voc os v exibidos entre os
botes de filtro na barra Show e o boto History.  (Para interromper a
pesquisa, pressione ESC; para encontrar a prxima ocorrncia, pressione
CTRL+N.)

Opes do Compilador e Seus Efeitos no ObjectBrowser

Embora voc possa utilizar o ObjectBrowser apenas no cdigo compilado, o
modo como compila seu projeto afeta aquilo que voc pode ver. Ao
utilizar ObjectBrowser  como ferramenta de depurao,  preciso mudar
algumas opes de compilao. (Se no fizer isso, ento voc pode
utilizar o ObjectBrowser s para inspecionar smbolos  que foram
declarados na seo Interface da unidade.) A tabela a seguir resume o
que voc pode fazer.

          Operaes do Compilador - Efeito no ObjectBrowser 

        Debug Information - Acrescenta a aptido para pesquisar smbolos
definidos na parte Implementation do mdulo.
        Local Symbols - Adiciona referncias de nmero de linha para
serem utilizadas na pgina References do painel Details.
        Symbol - Info Acrescenta todos os identificadores que voc
declarou em um determinado procedimento ou funo.

DICA: Estas opes quando ligadas retardam e aumentam o cdigo
compilado. Assegure-se de que estejam desligadas quando voc fizer a
compilao final.

O Painel Inspector

Quando voc est olhando para a hierarquia do objeto, o painel Inspector
exibe uma rvore de herana dos objetos; quando voc est olhando para
unidades, ele lhe  fornece uma lista de todas as unidades. (Isso inclui
aquelas que voc acrescentou bem como aquelas acrescentadas pelo prprio
Delphi, como System.) A idia  que  voc pode ver graficamente de onde
o objeto descende. (Observe na Figura 6.2 que TObject  o ltimo
ancestral.) Os objetos que descendem de um ancestral comum so  ramos de
um tronco que comea no objeto-pai. Voc pode realmente ampliar ou
reduzir a rvore dando um clique na pequena caixa  esquerda do nome. Um
sinal de adio  na caixa indica que voc pode fazer a sua expanso; um
sinal de subtrao indica que ela j foi expandida.

DICA: Se voc decidir trabalhar bastante com o ObjectBrowser, h algumas
simplificaes de teclado disponveis. Para estas consulte o tpico
"Object -Browser Keyboard  Shortcuts" na ajuda on-line.

        Quando voc seleciona um objeto no painel Inspector, o Delphi
atualiza o painel Details, que descreveremos em seguida.

O Painel Details

Esse painel tem trs pginas para Scope, Inheritance e References
respectivamente. A pgina Scope fornece-lhe uma lista dos smbolos
declarados no objeto atualmente  selecionado no painel Inspector. A
pgina Inheritance fornece uma rvore genealgica para o objeto; e a
pgina References fornece-lhe os nomes de arquivo e nmeros  de linha
onde o smbolo aparece em seu cdigo.

Inspeo Em-Profundidade

Se voc precisa olhar mais profundamente para um objeto, d um clique
duplo no objeto no painel Inspector. O Delphi move o contedo do painel
Details ao painel Inspector,  e fornece as declaraes do objeto que
voc selecionou no painel Details. Se voc, na verdade, quer olhar o
cdigo do objeto, selecione o objeto com o qual quer  trabalhar e
pressione CTRL+ENTER. O Delphi move o foco para a janela Code Editor e
move o cursor para o local em que o objeto foi declarado. Em geral, ao
ter selecionado  uma funo ou procedimento, o Delphi fornece o cdigo
para voc; quando o objeto  uma constante, uma propriedade, uma
varivel ou um tipo, o Delphi mostra a declarao  para voc.
