RESUMO DA AULA, CRIBS
Ciência da computação e tecnologia da informação. Compatibilidade de tipos de objetos (notas de aula) Diretório / Notas de aula, folhas de dicas Índice (expandir) PALESTRA Nº 12. Métodos 1. Métodos Uma declaração de método dentro de um tipo de objeto corresponde a uma declaração de método forward (forward). Assim, em algum lugar depois de uma declaração de tipo de objeto, mas dentro do mesmo escopo que o escopo da declaração de tipo de objeto, um método deve ser implementado definindo sua declaração. Para métodos procedurais e funcionais, a declaração de definição assume a forma de um procedimento normal ou declaração de função, com a exceção de que, neste caso, o identificador de procedimento ou função é tratado como um identificador de método. Para métodos construtores e destruidores, a declaração de definição assume a forma de uma declaração de método de procedimento, com a exceção de que a palavra reservada procedimento é substituída pela palavra reservada construtor ou destruidor. A declaração do método definidor pode, mas não precisa, repetir a lista de parâmetros formais do cabeçalho do método no tipo de objeto. Nesse caso, o cabeçalho do método deve corresponder exatamente ao cabeçalho no tipo de objeto em ordem, tipos e nomes de parâmetro e no tipo de retorno do resultado da função se o método for uma função. A descrição de definição de um método sempre contém um parâmetro implícito com o identificador Self, correspondente a um parâmetro de variável formal que possui um tipo de objeto. Dentro de um bloco de método, Self representa a instância cujo componente de método foi especificado para invocar o método. Assim, quaisquer alterações nos valores dos campos Self são refletidas na instância. O escopo de um identificador de bean de tipo de objeto se estende a blocos de procedimentos, funções, construtores e destruidores que implementam métodos desse tipo de objeto. O efeito é o mesmo que se uma instrução with da seguinte forma fosse inserida no início do bloco do método: com auto fazer começar ... end; Com base nessas considerações, a ortografia dos identificadores de componentes, parâmetros formais do método, Self e qualquer identificador introduzido na parte executável do método deve ser exclusivo. Se um identificador de método exclusivo for necessário, o identificador de método qualificado será usado. Ele consiste em um identificador de tipo de objeto seguido por um ponto e um identificador de método. Como acontece com qualquer outro identificador, um identificador de método qualificado pode opcionalmente ser precedido por um identificador de pacote e um ponto. Métodos Virtuais Os métodos são estáticos por padrão, mas, exceto pelos construtores, eles podem ser virtuais (incluindo a diretiva virtual na declaração do método). O compilador resolve as referências a chamadas de métodos estáticos durante o processo de compilação, enquanto as chamadas de métodos virtuais são resolvidas em tempo de execução. Isso às vezes é chamado de ligação tardia. Se um tipo de objeto declara ou herda qualquer método virtual, as variáveis desse tipo devem ser inicializadas chamando um construtor antes de chamar qualquer método virtual. Assim, um tipo de objeto que descreve ou herda um método virtual também deve descrever ou herdar pelo menos um método construtor. Um tipo de objeto pode substituir qualquer um dos métodos que herda de seus pais. Se uma declaração de método em um filho especificar o mesmo identificador de método que uma declaração de método no pai, a declaração no filho substituirá a declaração no pai. O escopo de um método de substituição se expande para o escopo do filho no qual o método foi introduzido e permanecerá assim até que o identificador do método seja substituído novamente. A substituição de um método estático é independente da alteração do cabeçalho do método. Por outro lado, uma substituição de método virtual deve preservar a ordem, os tipos e nomes de parâmetros e os tipos de resultado da função, se houver. Além disso, a redefinição deve incluir novamente a diretiva virtual. Métodos dinâmicos O Borland Pascal suporta métodos adicionais de ligação tardia chamados métodos dinâmicos. Os métodos dinâmicos diferem dos métodos virtuais apenas na maneira como são despachados em tempo de execução. Em todos os outros aspectos, os métodos dinâmicos são considerados equivalentes aos métodos virtuais. Uma declaração de método dinâmico é equivalente a uma declaração de método virtual, mas a declaração de método dinâmico deve incluir o índice de método dinâmico, que é especificado imediatamente após a palavra-chave virtual. O índice de um método dinâmico deve ser uma constante inteira entre 1 e 656535 e deve ser exclusivo entre os índices de outros métodos dinâmicos contidos no tipo de objeto ou em seus ancestrais. Por exemplo: procedimento FileOpen(var Msg: TMessage); 100 virtuais; Uma substituição de um método dinâmico deve corresponder à ordem, tipos e nomes dos parâmetros e corresponder exatamente ao tipo de resultado da função do método pai. A substituição também deve incluir uma diretiva virtual seguida pelo mesmo índice de método dinâmico que foi especificado no tipo de objeto ancestral. 2. Construtores e destruidores Construtores e destruidores são formas especializadas de métodos. Usado em conexão com a sintaxe estendida dos procedimentos padrão New e Dispose, construtores e destruidores têm a capacidade de colocar e remover objetos dinâmicos. Além disso, os construtores têm a capacidade de executar a inicialização necessária de objetos contendo métodos virtuais. Como todos os outros métodos, construtores e destruidores podem ser herdados e objetos podem conter qualquer número de construtores e destruidores. Construtores são usados para inicializar objetos recém-criados. Normalmente, a inicialização é baseada nos valores passados ao construtor como parâmetros. Um construtor não pode ser virtual porque o mecanismo de despacho de um método virtual depende do construtor que inicializou o objeto primeiro. Aqui estão alguns exemplos de construtores: construtor Field.Copy(var F: Field); começar Próprio := F; end; construtor Field.Init(FX, FY, FLen: inteiro; FName: string); começar X := FX; S := FY; GetMem(Nome, Comprimento(FNome) + 1); Nome^ := FNome; end; construtor TStrField.Init(FX, FY, FLen: inteiro; FName: string); começar herdado Init(FX, FY, FLen, FName); Field.Init(FX,FY,FLen,FName); GetMem(Valor, Len); Valor^ := ''; end; A ação principal de um construtor de um tipo derivado (filho), como o campo TSr acima. Init é quase sempre uma chamada para o construtor apropriado de seu pai imediato para inicializar os campos herdados do objeto. Após executar este procedimento, o construtor inicializa os campos do objeto que pertencem apenas ao tipo derivado. Os destruidores são o oposto dos construtores e são usados para limpar objetos depois de serem usados. Normalmente, a limpeza consiste em remover todos os campos de ponteiro do objeto. Nota Um destruidor pode ser virtual, e muitas vezes é. Um destruidor raramente tem parâmetros. Aqui estão alguns exemplos de destruidores: destruidor Campo Feito; começar FreeMem(Nome, Comprimento(Nome^) + 1); end; destruidor StrField.Done; começar FreeMem(Valor, Len); Campo Feito; end; O destruidor de um tipo filho, como o TSrField acima. Concluído, normalmente primeiro remove os campos de ponteiro introduzidos no tipo derivado e, em seguida, como última etapa, chama o destruidor de coletor apropriado do pai imediato para remover os campos de ponteiro herdados do objeto. 3. Destruidores O Borland Pascal fornece um tipo especial de método chamado coletor de lixo (ou destruidor) para limpar e excluir um objeto alocado dinamicamente. O destruidor combina a etapa de exclusão de um objeto com quaisquer outras ações ou tarefas necessárias para esse tipo de objeto. Você pode definir vários destruidores para um único tipo de objeto. O destruidor é definido junto com todos os outros métodos de objeto na definição de tipo do objeto: modelo Temployee = objeto Nome: string[25]; Título: string[25]; Taxa: Reais; construtor Init(AName, ATitle: String; ARate: Real); destruidor Feito; virtual; função GetName: String; função GetTitle: String; função GetRate: Taxa; virtual; função GetPayAmount: Real; virtual; end; Os destruidores podem ser herdados e podem ser estáticos ou virtuais. Como diferentes finalizadores tendem a exigir diferentes tipos de objetos, geralmente é recomendável que os destruidores sejam sempre virtuais para que o destruidor correto seja executado para cada tipo de objeto. O destruidor de palavras reservadas não precisa ser especificado para cada método de limpeza, mesmo que a definição de tipo do objeto contenha métodos virtuais. Destrutores realmente só funcionam em objetos alocados dinamicamente. Quando um objeto alocado dinamicamente é limpo, o destruidor executa uma função especial: ele garante que o número correto de bytes seja sempre liberado na área de memória alocada dinamicamente. Não pode haver preocupação em usar um destruidor com objetos alocados estaticamente; de fato, ao não passar o tipo do objeto para o destruidor, o programador priva um objeto desse tipo de todos os benefícios do gerenciamento dinâmico de memória no Borland Pascal. Destrutores realmente se tornam eles mesmos quando objetos polimórficos devem ser apagados e quando a memória que eles ocupam deve ser desalocada. Objetos polimórficos são aqueles objetos que foram atribuídos a um tipo pai devido às regras de compatibilidade de tipos estendidas do Borland Pascal. Uma instância de um objeto do tipo THourly atribuído a uma variável do tipo TEmployee é um exemplo de objeto polimórfico. Essas regras também podem ser aplicadas a objetos; um ponteiro para THourly pode ser atribuído livremente a um ponteiro para TEmployee, e o objeto apontado por esse ponteiro será novamente um objeto polimórfico. O termo "polimórfico" é apropriado porque o código que processa um objeto "não sabe" exatamente em tempo de compilação que tipo de objeto ele precisará processar. A única coisa que ele sabe é que esse objeto pertence a uma hierarquia de objetos que são descendentes do tipo de objeto especificado. Obviamente, os tamanhos dos tipos de objetos são diferentes. Então, quando chega a hora de limpar um objeto polimórfico alocado em heap, como Dispose sabe quantos bytes de espaço de heap devem ser liberados? Em tempo de compilação, nenhuma informação sobre o tamanho do objeto pode ser extraída de um objeto polimórfico. O destruidor resolve esse quebra-cabeça referindo-se ao local onde essas informações são gravadas - nas variáveis de implementação do TCM. Cada TBM de um tipo de objeto contém o tamanho em bytes desse tipo de objeto. A tabela de métodos virtuais de qualquer objeto está disponível através do parâmetro oculto Self, enviado ao método quando o método é chamado. Um destruidor é apenas um tipo de método e, portanto, quando um objeto o chama, o destruidor obtém uma cópia de Self na pilha. Assim, se um objeto for polimórfico em tempo de compilação, ele nunca será polimórfico em tempo de execução devido à ligação tardia. Para realizar essa desalocação de ligação tardia, o destruidor deve ser chamado como parte da sintaxe estendida do procedimento Dispose: Descarte(P, Pronto); (Uma chamada para o destruidor fora do procedimento Dispose não desaloca nenhuma memória.) O que realmente está acontecendo aqui é que o coletor de lixo do objeto apontado por P é executado como um método normal. No entanto, uma vez que a última ação é concluída, o destruidor procura o tamanho da implementação de seu tipo no TCM e passa o tamanho para o procedimento Dispose. O procedimento Dispose encerra o processo excluindo o número correto de bytes do espaço de heap que (o espaço) pertencia anteriormente a P^. O número de bytes a serem liberados estará correto independentemente de P apontar para uma instância do tipo TSalaried ou se apontar para um dos tipos filho do tipo TSalaried, como TCommissioned. Observe que o próprio método destruidor pode estar vazio e executar apenas esta função: destructorAnObject.Done; começar end; O que é útil neste destruidor não é propriedade de seu corpo, porém, o compilador gera código de epílogo em resposta à palavra reservada do destruidor. É como um módulo que não exporta nada, mas faz algum trabalho invisível executando sua seção de inicialização antes de iniciar o programa. Toda a ação acontece nos bastidores. 4. Métodos Virtuais Um método se torna virtual se sua declaração de tipo de objeto for seguida pela nova palavra reservada virtual. Se um método em um tipo pai for declarado como virtual, todos os métodos com o mesmo nome em tipos filho também deverão ser declarados virtuais para evitar um erro do compilador. A seguir estão os objetos da folha de pagamento de exemplo, devidamente virtualizados: modelo PEfuncionário = ^TEFuncionário; Temployee = objeto Nome, Título: string[25]; Taxa: Reais; construtor Init(AName, ATitle: String; ARate: Real); função GetPayAmount : Real; virtual; função GetName : String; função GetTitle : String; função GetRate : Real; procedimento Mostrar; virtual; end; PHhourly = ^THourly; THourly = object(TEFuncionário); Hora: Inteiro; construtor Init(AName, ATitle: String; ARate: Real; Time: Integer); função GetPayAmount : Real; virtual; função GetTime : Inteiro; end; PSAssalariado = ^TSAssalariado; TSalario = objeto(TEEmpregado); função GetPayAmount : Real; virtual; end; PComissionado = ^TComissionado; TComissionado = objeto(Assalariado); Comissão : Real; Valor de Vendas : Real; construtor Init(AName, ATitle: String; ARate, AComissão, ASVendasValor: Real); função GetPayAmount : Real; virtual; end; Um construtor é um tipo especial de procedimento que faz algum trabalho de configuração para o mecanismo de método virtual. Além disso, o construtor deve ser chamado antes de qualquer método virtual ser chamado. Chamar um método virtual sem primeiro chamar o construtor pode bloquear o sistema e não há como o compilador verificar a ordem na qual os métodos são chamados. Todo tipo de objeto que possui métodos virtuais deve ter um construtor. aviso O construtor deve ser chamado antes de qualquer outro método virtual ser chamado. Chamar um método virtual sem uma chamada anterior ao construtor pode causar um bloqueio do sistema e o compilador não pode verificar a ordem em que os métodos são chamados. Nota Para construtores de objetos, sugere-se usar o identificador Init. Cada instância de objeto distinto deve ser inicializada com uma chamada de construtor separada. Não basta inicializar uma instância de um objeto e depois atribuir essa instância a outras. Outras instâncias, mesmo que contenham dados válidos, não serão inicializadas com um operador de atribuição e bloquearão o sistema em qualquer chamada para seus métodos virtuais. Por exemplo: var FBee, GBee: Bee; { cria duas instâncias do Bee } começar FBee.Init(5, 9) { chamada do construtor para FBee } GBee := FBee; { Gbee é inválido! } end; O que exatamente um construtor cria? Cada tipo de objeto contém algo chamado tabela de método virtual (VMT) no segmento de dados. O TVM contém o tamanho do tipo de objeto e, para cada método virtual, um ponteiro para o código que executa esse método. Um construtor estabelece um relacionamento entre a implementação de chamada do objeto e o tipo TCM do objeto. É importante lembrar que existe apenas um TBM para cada tipo de objeto. Instâncias separadas de um tipo de objeto (ou seja, variáveis desse tipo) contêm apenas a conexão com o TBM, mas não o próprio TBM. O construtor define o valor dessa conexão para TBM. É por isso que em nenhum lugar você pode iniciar a execução antes de chamar o construtor. 5. Campos de dados de objetos e parâmetros de métodos formais A implicação do fato de que métodos e seus objetos compartilham um escopo comum é que os parâmetros formais de um método não podem ser idênticos a nenhum dos campos de dados do objeto. Esta não é uma nova limitação imposta pela programação orientada a objetos, mas sim as mesmas velhas regras de escopo que Pascal sempre teve. Isso é o mesmo que impedir que os parâmetros formais de um procedimento sejam idênticos às variáveis locais do procedimento: procedimento CrunchIt(Crunchee: MyDataRec, Crunchby, Código de Erro: inteiro); var A, B: caractere; Código de erro: inteiro; começar . . . As variáveis locais de um procedimento e seus parâmetros formais compartilham um escopo comum e, portanto, não podem ser idênticos. Você obterá "Erro 4: identificador duplicado" se tentar compilar algo assim, o mesmo erro ocorre quando você tenta definir um parâmetro de método formal para o nome do campo do objeto ao qual o método pertence. As circunstâncias são um pouco diferentes, pois colocar o cabeçalho do procedimento dentro de uma estrutura de dados é um aceno para uma inovação no Turbo Pascal, mas os princípios básicos do escopo do Pascal não mudaram. Autor: Tsvetkova A.V. << Voltar: Métodos (Métodos. Construtores e destruidores. Destruidores. Métodos virtuais. Campos de dados de objetos e parâmetros de métodos formais) >> Encaminhar: Montador (Sobre assembler. Modelo de software de microprocessador. Registros de usuário. Registros de uso geral. Registros de segmento. Registros de status e controle) Recomendamos artigos interessantes seção Notas de aula, folhas de dicas: ▪ Metodologias de ensino de psicologia. Notas de aula ▪ fisiologia patológica. Berço ▪ História da cultura. Notas de aula Veja outros artigos seção Notas de aula, folhas de dicas. Leia e escreva útil comentários sobre este artigo. Últimas notícias de ciência e tecnologia, nova eletrônica: A existência de uma regra de entropia para o emaranhamento quântico foi comprovada
09.05.2024 Mini ar condicionado Sony Reon Pocket 5
09.05.2024 Energia do espaço para Starship
08.05.2024
Outras notícias interessantes: ▪ Conversor SIMO PMIC MAX77654 ▪ Ondas de conversão de chip fotônico com alta eficiência ▪ Película que aumenta a resistência ao impacto da tela do smartphone ▪ Peixes de aquário para astronautas Feed de notícias de ciência e tecnologia, nova eletrônica
Materiais interessantes da Biblioteca Técnica Gratuita: ▪ seção do site Reguladores de energia, termômetros, estabilizadores de calor. Seleção de artigos ▪ artigo Mercado de pulgas. expressão popular ▪ artigo Lago Ladoga. milagre da natureza ▪ artigo Antenas de televisão. Diretório ▪ artigo S-metr para rádio HF. Enciclopédia de rádio eletrônica e engenharia elétrica
Deixe seu comentário neste artigo: Todos os idiomas desta página Página principal | Biblioteca | Artigos | Mapa do Site | Revisões do site www.diagrama.com.ua |