Conceitos Essenciais: TADs, Estruturas e Tipagem

Classificado em Computação

Escrito em em português com um tamanho de 6,65 KB

Tipos Abstratos de Dados (TADs)

Agrupam a estrutura de dados juntamente com as operações que podem ser feitas sobre esses dados, encapsulando a estrutura de dados. Os usuários do TAD só têm acesso a algumas operações disponibilizadas sobre esses dados. O usuário só enxerga a interface, não a implementação, podendo abstrair da implementação específica. Qualquer modificação nessa implementação fica restrita ao TAD. A escolha de uma representação específica é fortemente influenciada pelas operações a serem executadas.

Implementação de TADs

Em linguagens orientadas a objeto (C++, Java), a implementação é feita através de classes. Em linguagens estruturadas (C, Pascal), a implementação é feita pela definição de tipos juntamente com a implementação de funções.

Estruturas (Structs) em C/C++

Uma estrutura é uma coleção de uma ou mais variáveis, possivelmente de tipos diferentes, colocadas juntas sob um único nome para manipulação conveniente. Por exemplo, para representar um aluno são necessárias as informações nome, matrícula e nota. Ao invés de criar três variáveis, é possível criar uma única variável contendo três campos. Em C, usa-se a construção struct para representar esse tipo de dado.

Declaração de Tipos

Para simplificar, uma estrutura ou mesmo outros tipos de dados podem ser definidos como um novo tipo, utilizando a construção typedef.

TADs em C

Em C, usa-se a definição de tipos juntamente com a implementação de funções que agem sobre aquele tipo. Como boa regra de programação, evita-se acessar o dado diretamente, fazendo o acesso apenas através das funções. Mas, diferentemente de C++ e Java, não há uma forma de proibir o acesso (encapsulamento).

Tipagem Forte e Fraca

Linguagens Fortemente Tipadas: O compilador e o ambiente de execução se encarregam de fazer a verificação de tipos. Verificação de Tipos: operandos, operadores, atribuições, subprogramas. Verificação Estática: realizada pelo compilador. Linguagem Fracamente Tipada: Uma linguagem que não garante a ausência de erros de tipos, pelo menos de forma estática (em tempo de compilação).

Violação de Tipos

Um dos principais objetivos da utilização de sistemas de tipos em linguagens de programação é permitir a detecção de erros (de tipos). Considera-se um erro toda e qualquer violação das regras definidas pela linguagem de programação. A detecção de erros pode ser feita de forma estática ou de forma dinâmica, caso seja possível a detecção somente durante a execução do programa. Exemplos:

  • Estática: violação de tipo por atribuição.
  • Dinâmica: violação de tipo por leitura, com valor proveniente do meio externo, somente poderá ser detectada pelo ambiente de execução.

Portabilidade e Representação de Tipos

Pessoas que apregoam não se preocupar com portabilidade geralmente fazem isso porque usam um único sistema e sentem que podem dar-se ao luxo de achar que 'a linguagem é aquilo que meu compilador implementa'. Esta é uma visão restrita e míope. Se seu programa é um sucesso, é muito provável que seja portado, de modo que alguém vai ter que procurar e corrigir problemas relacionados com características dependentes da implementação. Além disso, frequentemente é necessário compilar programas com outros compiladores para o mesmo sistema, e mesmo uma versão futura de seu compilador favorito pode fazer algumas coisas de maneira diferente da maneira atual.

Tamanhos de Tipos em C++

Os tamanhos dos objetos de C++ são expressos em múltiplos do tamanho de um char. Um char pode armazenar um caractere do conjunto de caracteres da máquina. É garantido que um char tem pelo menos 8 bits, um short pelo menos 16 bits e um long pelo menos 32 bits. Por definição, o tamanho de char é 1. O tamanho de um objeto ou tipo pode ser obtido usando o operador sizeof.

Representação de Tipos

A representação interna pode ser direta, refletindo a própria estrutura lógica do hardware, ou indireta, quando a variável tem sua representação interna associada a um descritor de tipo. A representação interna depende do projeto da linguagem de programação e da arquitetura da máquina onde é feita a implementação da linguagem. Por exemplo, a representação de reais.

Equivalência, Compatibilidade e Inferência

A equivalência de tipos existe quando dois valores possuem o mesmo tipo. Exemplo: type natural: 1.. maxint; var n1, n2: natural;

A compatibilidade define quando um tipo pode ser usado em lugar de outro em um determinado contexto. Exemplo: var i: integer; ........ i := n1 + 10;

A inferência de tipos define o tipo de uma expressão com base nos tipos de operandos envolvidos e a operação a ser realizada.

Conversão de Tipos

Quando os tipos envolvidos em uma expressão não são equivalentes, a linguagem oferece a possibilidade de conversão de tipos. A conversão implícita ou automática é feita com base nas regras definidas sem a interferência do programador. A conversão explícita é codificada diretamente pelo programador. Termos em inglês: casting, coercion.

Conversão de Tipos Primitivos

A conversão de tipos primitivos é ditada pelas regras da linguagem de programação. Normalmente admite a conversão de um tipo de representação menor para um tipo de representação maior. Por exemplo, em Java, a conversão entre tipos primitivos — exceto o tipo boolean que não admite conversão — considera o tamanho do tipo (8, 16, 32, 64 bits).

Formas de Conversão

A conversão pode ser feita de três maneiras: por atribuição, ou conversão implícita para o tipo do lado esquerdo do comando de atribuição; por promoção aritmética para o tipo de resultado esperado da operação (inferência); por conversão explícita (casting).

Seja float f, int i, float r;

Exemplo de atribuição: f = i;

Exemplo de promoção: r = f / i;

Exemplos de casting: i = (int) f; r = (float) i / f;

Entradas relacionadas: