Object Pascal e Delphi Programas e Units 1 Sumário Estrutura de um programa e sintaxe Estrutura e sintaxe de uma unit Referência a units e a cláusula uses 2 Estrutura de um programa e sintaxe Introdução O cabeçalho do programa A cláusula uses do programa O bloco 3 Introdução Um programa em Object Pascal é constituído de módulos de código fonte chamados units. Cada unit é armazenada em seu próprio arquivo e compilada separadamente. As unidades compiladas (arquivos .dcu) são ligadas para criar uma aplicação. Units permitem Dividir grandes programas em módulos que podem ser editados separadamente Criar bibliotecas que possam ser compartilhadas por diversos programas Distribuir bibliotecas para outros programadores sem tornar disponível o código fonte 4 Introdução (cont.) No Pascal tradicional todo o código fonte, incluindo o programa principal é armazenado em arquivos .pas. Delphi usa um arquivo Project (.dpr) para armazenar o programa principal enquanto a maioria do código reside em arquivos unit (.pas). Cada aplicação (ou Projeto) consiste de um único arquivo Project e um ou mais arquivos unit. Pelo menos a unit System é criada automaticamente pelo programa. Para construir um project o compilador necessita de um arquivo fonte ou um arquivo já compilado (.dcu) para cada unit. 5 Programas e Units Um programa contém Um cabeçalho de programa Uma clausula uses (opcional) Um bloco de declarações e comandos O cabeçalho do programa especifica o nome do programa. A cláusula uses contém a lista das units usadas pelo programa. O bloco contém declarações e comandos que são executados quando o programa for executado. Um exemplo de programa denominado Editor é mostrado a seguir, lembrando que todos os arquivos fonte terminam por um ponto. 6 Programas e Units (cont.) 1 program Editor; 2 3 uses 4 Forms, 5 REAbout in 'REABOUT.PAS' {AboutBox}, 6 REMain in 'REMain.pas' {MainForm}; 7 8 {$R *.RES} 9 10 begin 11 Application.Title := 'Text Editor'; 12 Linha 1 3a6 8 Conteúdo Cabeçalho do Programa Cláusula uses Diretiva de compilação ligando o arquivo de recursos do projeto ao programa 10 a Bloco de comandos a serem executados quando o programa “rodar” 14 Application.CreateForm(TMainForm , MainForm); 13 Application.Run; 14 end. 7 Programas e Units (cont.) Este arquivo project é bem típico da linguagem pois eles são usualmente bem pequenos já que a lógica fica nos arquivos das units. Os arquivos project são gerados e mantidos pelo Delphi sendo raro que se necessite edita-los manualmente. 8 O cabeçalho do programa O cabeçalho de um programa consiste de Palavra reservada program Identificador igual ao nome do project Separador ponto e vírgula No Pascal tradicional existiam parâmetros entre o identificador e o ponto e vírgula, que, se existirem, serão ignorados pelo Delphi. 9 A cláusula uses do programa A cláusula uses contém a lista das units usadas pelo programa. As units referenciadas, por sua vez, podem ter cláusulas uses também. 10 O bloco O bloco contém declarações e comandos que são executados quando o programa for executado. Muitas vezes o bloco consiste de um comando composto, delimitado pelas palavras reservadas begin e end, cujos comandos componentes são chamadas a métodos do objeto Application do project. O bloco pode conter declarações de constantes, tipos, variáveis, procedimentos e funções. Estas declarações devem preceder os comandos do bloco. 11 Estrutura e sintaxe de uma unit Introdução O cabeçalho da unit A seção interface A seção implementation A seção initialization A seção finalization 12 Introdução Uma unit consiste de tipos (incluindo classes), constantes, variáveis e rotinas (funções e procedimentos). Cada unit é definida em seu arquivo .pas. Um arquivo de unit tem a seguinte composição Cabeçalho de unit Seção de interface Seção de implementatiion Seção de initialization (opcional) Seção de finalization (opcional) A unit termina com a palavra reservada end seguida por um ponto 13 Exemplo de unit unit Unit1; interface uses { Aqui fica a lista de units } { Aqui fica a seção interface } implementation uses { Aqui fica a lista de units } { Aqui fica a seção Implementation } initialization { Aqui fica a seção Initialization } finalization { Aqui fica a seção Finalization } end. 14 O cabeçalho da unit O cabeçalho de uma unit consiste de Palavra reservada unit Identificador igual ao nome do arquivo aonde está armazenada a unit Separador ponto e vírgula A unit alfa estará armazenada no arquivo alfa.pas e, depois de compilada, o resultado será armazenado no arquivo alfa.dcu. Os nomes de units devem ser únicos em um mesmo project. Mesmo que armazenadas em diretórios distintos os nomes não podem se repetir. 15 A seção interface A seção interface inicia após a palavra reservada interface e vai até o início da seção implementation. A seção interface declara constantes, tipos, variáveis, procedimentos e funções que estão disponíveis para os clientes, isto é, outras units que usam a unit na qual foram feitas as declarações. Estas entidades são chamadas de públicas. 16 A seção interface (cont.) A declaração de um procedimento ou função inclui apenas o cabeçalho da rotina. O bloco do procedimento ou função aparecerá na seção implementation. Tudo se passa como se ocorresse uma declaração forward. A declaração de uma classe na seção interface deve incluir declarações de todos os membros da classe. A seção interface pode ter sua própria cláusula uses, imediatamente após a palavra reservada interface. 17 A seção implementation A seção implementation inicia com a palavra reservada implementation e vai até o início da seção initialization, se esta existir. Caso contrário vai até o final da unit. Esta seção define os procedimentos e funções declarados na seção interface. Estas funções e procedimentos podem ser definidos em qualquer ordem. A lista de parâmetros dos cabeçalhos de funções e procedimentos públicos pode ser omitida. 18 A seção implementation (cont.) A seção implementation, além da definição de rotinas, pode declarar constantes, tipos (incluindo classes), variáveis, procedimentos e funções provadas da unit, sendo inacessíveis aos clientes. A seção initialization pode ter sua própria cláusula uses, imediatamente após a palavra reservada initialization. 19 A seção initialization A seção initialization (opcional) inicia com a palavra reservada initialization e vai até o início da seção finalization, se esta existir. Caso contrário vai até o final da unit. Esta seção contém comandos que são executados no início do programa. A ordem de execução das seções initialization das diversas units do programa é dada pela ordem em que as units aparecem na cláusula uses do cliente. 20 A seção finalization A seção finalization é opcional e só pode surgir nas units que possuam cláusula initialization. Ela inicia após a palavra reservada finalization e vai até o final da unit, contendo comandos que são executados quando o programa principal termina. Normalmente é executada para liberar recursos alocados na seção initialization. Quando houver mais de uma seção finalization elas são executadas em ordem inversa à ordem de execução da seção initialization. Se a aplicação inicializa as units A, B e C, nessa ordem, ela vai finaliza-las na ordem C, B e A. 21 Referência a units e a cláusula uses Introdução A sintaxe da cláusula uses Referências múltiplas e indiretas Referência circular entre units 22 Introdução A cláusula uses contém a lista das units usadas pelo programa, biblioteca ou unit na qual a cláusula aparece. Uma cláusula uses pode ocorrer em O arquivo project para um programa ou biblioteca Seção interface de uma unit Seção implementation de uma unit A unit System é usada automaticamente por todas as aplicações Delphi e não pode ser listada explicitamente em uma cláusula uses. Na maioria das vezes Delphi coloca todas as units necessárias na cláusula uses quando gera e mantém o arquivo fonte. 23 A sintaxe da cláusula uses A cláusula uses consiste na palavra reservada uses seguida de um ou mais nomes de units, separados por vírgulas e terminada por um ponto e virgula. Exemplos uses Forms, Main; uses Windows, Messages, SysUtils, Strings, Classes, Unit2, MyUnit; 24 A sintaxe da cláusula uses (cont.) Na cláusula uses de um programa ou biblioteca qualquer nome de unit pode ser seguido da palavra reservada in e o nome de um arquivo fonte com ou sem o caminho do diretório, envolvido em aspas simples. Os diretórios podem ser absolutos ou relativos. Exemplos: uses Windows, Messages, SysUtils, Strings in 'C:\Classes\Strings.pas', Classes; uses Forms, Main, Extra in '..\EXTRA\EXTRA.PAS'; 25 A sintaxe da cláusula uses (cont.) A IDE Delphi espera encontrar nomes de units coincidindo com nomes de arquivos fonte no diretório no qual residam. Usa-se in quando não houver clareza, como O arquivo fonte está em um diretório diferente do arquivo project e o esse diretório (do fonte) não está no caminho de busca do compilador ou no caminho de busca da Biblioteca Delphi Diferentes diretórios no caminho de busca possuem units com o mesmo nome Uma aplicação tipo console está sendo compilada pela linha de comando e foi nomeada uma unit com um identificador que não coincide com o nome de seu arquivo fonte 26 A sintaxe da cláusula uses (cont.) No caso da cláusula uses ser usada em uma unit não se pode indicar aonde procurar o arquivo fonte. Todas as units referenciadas devem estar no caminho de busca do compilador, ou no caminho de busca das bibliotecas Delphi, ou no mesmo diretório corrente. 27 Referências múltiplas e indiretas A ordem em que as units aparecem na cláusula uses determina a ordem de sua inicialização e afeta o modo pelo qual os identificadores são localizados pelo compilador. Se duas units declaram uma variável, constante, tipo, procedimento ou função com o mesmo nome, o compilador usa aquele da unit listada em último lugar na cláusula uses (para acessar o identificador da outra unit deve-se adicionar um qualificador: NomeDaUnit.Identificador. Uma cláusula uses deve incluir apenas units usadas diretamente pelo programa ou unit na qual a cláusula aparece. Assim se a unit A referencia variável, constante, tipo, procedimento ou função declaradas na unit B, então A deve explicitamente ter a cláusula uses para B. Se, por sua vez, a unit B referenciar identificadores a unit C, então a unit A é indiretamente dependente da unit C mas não necessita incluir a unit C na cláusula uses pois o compilador faz isto automaticamente. 28 Referências múltiplas e indiretas (cont.) program Prog; uses Unit2; const a = b; ... unit Unit2; interface uses Unit1; const b = c; ... unit Unit1; interface const c = 1; ... Neste exemplo Prog depende diretamente de Unit2 que depende diretamente de Unit1. Como Unit1 não aparece na cláusula uses de Prog, os identificadores declarados em Unit1 não são acessíveis a Prog. 29 Referências múltiplas e indiretas (cont.) Para compilar um módulo cliente o compilador necessita localizar todas as units de que o cliente dependa, direta ou indiretamente. A menos que o código fonte dessas units tenha sido modificado o compilador se contenta apenas com os arquivos .dcu, não necessitando dos arquivos .pas. Quando são feitas modificações na seção interface de uma unit, outras units que dependam dela precisam ser recompiladas. Todavia quando as modificações são feitas na seção de implementação ou outras seções da unit, as units dependentes não precisam ser recompiladas. 30 Referência circular entre units Quando units referenciam uma a outra direta ou indiretamente, diz-se que as units são mutuamente dependentes. São permitidas dependências mutuas desde que não haja caminhos circulares conectando a cláusula uses de uma seção interface à clausula uses de outra. Partindo da seção interface de uma unit não deve ser possível retornar a essa unit seguindo as referencias através das seções interface de outras units. 31 Referência circular entre units (cont.) Para que um padrão de dependências mútuas seja válido cada caminho de referencia circular deve passar através da cláusula uses de, pelo menos, uma seção implementation. No caso mais simples de duas units mutuamente dependentes isto significa que as units não podem listar-se mutuamente na cláusula uses de suas seções interface. O exemplo a seguir leva a uma condição de erro. 32 Referência circular entre units (cont.) unit Unit1; interface uses Unit2; ... unit Unit2; interface uses Unit1; Contudo, as duas units podem referenciar uma a outra se uma das referencias for movida para a seção implementation. 33 Referência circular entre units (cont.) unit Unit1; interface uses Unit2; ... unit Unit2; interface uses Unit1; unit Unit1; interface uses Unit2; ... unit Unit2; interface ... implementation uses Unit1; ... 34 Referência circular entre units (cont.) Para reduzir a probabilidade de referências circulares é boa idéia listar as units na cláusula uses da seção implementation sempre que possível. Apenas quando os identificadores de outra unit forem usados na seção interface será necessário listar aquela unit na cláusula uses da seção interface. 35