Algumas vezes é possível utilizar alguns paradigmas de orientação à objetos em C. Ao se projetar uma biblioteca, podemos encapsular o conteúdo das structs usando tipos incompletos e provendo funções para manipular o conteúdo destas.
Imagine uma biblioteca que cria um “objeto” para representar uma pessoa. Esta biblioteca provê um cabeçalho person.h com funções para manipular o “objeto”.
typedef struct person person; person *person_new(char *name, int age); void person_free(person *handler); void person_print(person *handler);
Note que não existe uma descrição da struct person no cabeçalho. A única forma então de manipular esta struct é usando as funções, porque os atributos da struct não são conhecidos. Esta struct portanto caracteriza um tipo incompleto, mas apenas do ponto de vista dos usuários da biblioteca. Em sua implementação, a biblioteca conhece o conteúdo de person e consegue manipulá-los, como vemos a seguir.
#include <string.h> #include <stdio.h> #include <stdlib.h> #include "person.h" struct person { char *name; int age; }; person *person_new(char *name, int age) { person *new = malloc(sizeof(*new)); new->name = strdup(name); new->age = age; return new; } void person_free(person *handler) { free(handler->name); free(handler); } void person_print(person *handler) { printf("%s - %d\n", handler->name, handler->age); }
A vantagem de se encapsular os dados, forçando esta política através da técnica apresentada, é que a implementação da biblioteca pode ser alterada sem impacto em seus clientes. person_new poderia checar a validade do atributo age, retornando um ponteiro nulo caso seja passado uma idade negativa. O código seguinte ilustra um possível cliente da biblioteca, note que não há referência aos atributos de struct person.
#include <person.h> int main(void) { person *mike = person_new("Mike", 21); person_print(mike); person_free(mike); return 0; }
A primeira vez que vi uma biblioteca fazendo uso extenso desta técnica foi no projeto OpenSync, que inspirou este post.
Encapsulamento em C!!! Me parece ser uma boa para a validação de campos!
Interessante a técnica :D
Usei ela em uma experiência que fiz. Gostaria de saber o que acha:
http://murilo.wordpress.com/2009/08/05/como-programar-em-c-orientado-a-objetos/
Abraço!
Gostei do post.
Existem outras bibliotecas que implementam essa técnica.
No ano passado eu escrevi sobre isso também:
http://blog.blabos.org/2008/05/membros-privados-em-estruturas-c
Abração
E usado largamente este tipo de técnica em códigos relacionados ao GNOME! (Conceitos envolvendo GObject, dados privados, …)
Muito legal!!!
Nunca vi essa nomenclatura de “tipos incompletos”, conheço essa maneira de prover funções para manipular structs pelo nome de “tipos opacos”.
Com tipos opacos, programas utilizam a biblioteca apenas através de referências as estruturas, e realizam operações sobre estas através de funções.
Dessa maneira, a biblioteca esconde detalhes de sua implementação, os programas não devem setar valores diretamente nos campos da estrutura, deve-se sempre utilizar funções da bibilioteca.
Um exemplo de biblioteca que utiliza isso e que vários não perceberam, é quando se manipula arquivos. fopen() retorna um ponteiro para um handler, depois utiliza-se outras funções como ftell(), fwrite() e ao final fclose(), porém em nenhum momento se mexeu diretamente com o handler :)
sqlite e libevent são também exemplos de bibliotecas em C que utilizam-se de tipos opacos.
Espero ter ajudado :)
Ambos os nomes estão corretos. Já vi ambas nomenclaturas, mas a maioria das vezes, Opaque Pointers era usado quando se falava de C++.
http://tinobox.com/wordpress/c-programming/incomplete-types-in-c-programming/
http://www.ibm.com/developerworks/library/pa-ctypes1/
[]’s
A tradução de termos técnicos é sempre complicada. Em linguagem Scala temos os “companion Objects” os quais traduzí como sendo “objetos complementares”, porém há incontáveis outras possibilidades para esse termo.
Essa é uma dificuldade para a difusão de conceitos de programação em português. Temos que nos adaptar a uma realidade onde a lingua inglesa é predominante.
Na minha opinião, “tipos opacos” soa correto também.
Preciso de uma orientação a respeito de formação acadêmica.
Para ter competência formal no assunto abordado acima ( e em C/C++/Java/Python), devo fazer Engenharia de Software ou Ciência da Computação? Penso que Ciência da Computação versa mais sobre os fundamentos da computação, porém tenho visto em outros sites que os autores de textos correlatos, com formação em Ciência da Computação, demonstram notório saber em assuntos semelhantes, talvez até pela larga experiência de atuação acadêmica. Tenho conhecimento leigo em C/C++, Java, Python.
A título de curiosidade, cheguei à esta página vindo de http://murilo.wordpress.com/2009/08/05/como-programar-em-c-orientado-a-objetos/ pois costumo estudar como autodidata
Grato a quem se dispuser a responde-me.
Parabéns pelo artigo mais uma ajuda valiosa ao mundo da programação!