Programação genérica é um paradigma de programação no qual os algoritmos são escritos em uma gramática estendida, de forma a adaptar-se através da especificação das partes variáveis que são definidas na instância do algoritmo.
Especificamente, a gramática estendida e eleva um elemento não variável ou uma construção implícita na gramática com base para uma variável ou constante, permitindo a utilização do código genérico.
É diferente da forma normal de programação, que na medida em que invoca de certa forma as facilidades de metaprogramação da linguagem.
Como isso ocorre em uma extensão da linguagem, novas semânticas são introduzidas e a linguagem é enriquecida no processo.
Todo esse processo é relacionada com a metaprogramação, mas não envolve a geração de código fonte, pelo menos visivelmente ao programador.
É diferente também da programação por macros, já que esta refere-se somente a busca e substituição de termos, não fazendo parte da gramática da linguagem, implementada somente na fase de pré-processamento do código.
Para efeitos práticos, o paradigma permite que um parâmetro assuma diferentes tipos de dados desde que certas regras sejam mantidas, como sub-tipos e assinaturas.
Por exemplo, para criar uma lista usando programação genérica, uma possível declaração seria List<T>, no qual T é o tipo de dado, para instanciar, poderia-se usar List<Inteiro> ou List<Animal>, já que o conceito de lista independe do tipo utilizado.
Entre linguagens orientadas a objeto, C++, Linguagem D, BETA, Eiffel e versões de Java (1.5 e acima) fornecem o paradigma genérico. Visual Basic .NET, C# e Delphi.Net começaram a fornecer o paradigma a partir do .NET 2.0. Muito antes de todas as linguagens mencionadas, programação genérica já havia sido implementada na década de 1970 em linguagens como CLU e Ada.
Mas somente o conceito de templates do C++ que popularizou o conceito, a técnica permite que algoritmos sejam escritos independente dos tipos de dados utilizados.
Os autores do conceituado livro de 1995 Design Patterns referem-se à programação genérica como tipos parametrizados, o que permite que um tipo possa ser definido sem especificar todos os outros tipos que ele utilizada, os autores ainda descrevem que tal técnica é muito poderosa, especialmente quando combinada com o padrão Delegar.
A Utilização da Programação Genérica em templates C++
Os templates são de grande utilidade para programadores C++, especialmente quando combinado com herança múltipla e sobrecarga de operadores, a biblioteca padrão do C++ fornece várias funções úteis dentro de uma rede de templates conectados, templates em C++ podem também serem usados para funções diversas à programação genérica.
Um exemplo é a meta programação por templates, um método para executar algoritmos em tempo de compilação ao invés de execução.
Visão Geral da Programação Genérica
Existem dois tipos de templates, uma função template se comporta como uma função que pode aceitar argumentos de vários tipos diferentes.
Por exemplo, a biblioteca STL do C++ contém funções template max(x, y) que retornam ou x ou y, qual for maior. max() poderia ser definida assim:
template <typename T> T max(T x, T y) { if (x < y) return y; else return x; } |
Esse template pode ser chamado para diversos tipos de dados:
cout << max(3, 7); // imprime 7 -> tipo de dado é ”int”cout << max(3.239, 5.238); // imprime 5.238 -> tipo de dado é ”float” |
O compilador determina, ao examinar os argumentos, que a primeira chamada possui assinatura max(int, int) e instancia uma versão da função no qual o tipo T é int.
Da mesma forma, ele determina que a segunda chamada possui assinatura max(float, float), e instancia a função para float.
Isso somente funciona pois os tipos int e float definem a operação <. Para tipos de dados próprios (como classes), é possível usar sobrecarga de operadores para definir < para seu tipo, permitindo que ele seja usado na função max().
Apesar de parecer um benefício simples, no contexto de bibliotecas como a STL isso permite que programadores tenham mais funcionabilidade para seus tipos definidos ao definir os operadores.
Por exemplo, definir < permite que um tipo possa ser usado com as funções padrão sort(), stable_sort(), e binary_search(); além de estruturas de dados como sets, entre outras.
Como exemplo contrário, o tipo padrão complex não define o operador <, pois não existe ordenação definida em números complexos. Logo max(x, y) não poderá ser utilizado se x e y são do tipo complex.
Da mesma forma, outros templates que necessitam de < não podem ser utilizados com complex.
Uma classe template amplia o mesmo conceito para classes. Elas são usadas geralmente para criar containers genéricos.
Por exemplo, a STL possui o container list, que representa uma lista encadeada, para criar listas encadeadas de inteiros, utiliza-se list<int>.
Da mesma forma, uma lista de cadeias de texto é definida como list<string>. list possui um conjunto de funções padrão associadas a ele, que funcionam independente do tipo utilizado para a lista.
Vantagens e Desvantagens da Programação Genérica
Algumas aplicações de templates, como a função max(), eram anteriormente criadas por macros de função:
# define max(a,b) ( (a) < (b) ? (b) : (a) ) |
Tanto macros quanto templates são instanciados em tempo de compilação, os macros são sempre expandidas no próprio local onde foram utilizadas; os templates também podem ser expandidos no próprio local onde foram utilizadas, se o compilador considerar adequado logo tanto macros de função quanto funções template não exigem mais processamento na execução.
Apesar disso, templates são considerados uma evolução sobre macros nesse propósito, eles verificam a tipagem de dados, evitam alguns dos erros mais comuns ao se utilizar macros excessivamente e são mais robustos que macros.
Antigamente, os compiladores não tinham bom suporte para templates. No entanto, praticamente todos os compiladores atuais do mercado conseguem lidar com templates sem problemas.
Ainda assim, existem duas desvantagens no uso de templates, primeiro é que quase todos os compiladores produzem mensagens de erros em templates que são confusas e de pouca ajuda, o que torna o desenvolvimento mais difícil. Segundo, é que quanto mais tipos de dados diferentes utilizados em templates, geralmente mais código é gerado pelo compilador (uma versão da função ou classe para cada tipo de dado), logo, o uso indiscriminado pode levar a executáveis excessivamente grandes.
O primeiro problema mencionado será eliminado com a chegada dos Conceitos novo padrão C++ (C++0x, que está previsto para 2009).
Através dos conceitos será possível estabelecer um mecanismo formal para verificação de tipos e operações esperadas por um parâmetro template, com isso, mensagens de erro serão sempre claras e objetivas.
Então é isso pessoal, caso tenha gosta do conteúdo e tenha alguma dúvida, deixe seu comentário no campo disponível logo abaixo.
Ah.. e não se esqueça de visitar o nosso site, estamos com uma ótima promoção de 30 dias de teste grátis para todos os nossos planos de hospedagem de sites.
https://www.hostec.com.br/hospedagem-de-sites