Descobertas

Diretamente do cotidiano de um programador

O que é herança prototípica?

leave a comment »

Inicialmente eu queria falar bastante sobre herança prototípica em um post só, mas iria ficar muito maçante. Ainda mais que eu não sou expert no assunto e só quero clarear os conceitos pra mim mesmo e, se possível, abrir um espaço pra discussão (aquela discussão sadia que raramente se vê por aí) na área de comentários.

Tudo começou quando eu estava lendo um post no blog do Rodrigo Kumpera, em que ele deu umas dicas de papers pra ler. Li esse paper sobre a linguagem Self e achei muito interessante o fato de alguns conceitos citados poderem ser usados em duas linguagens que eu uso bastante, que são o Ruby e o Javascript.

Herança prototípica é uma estratégia para reutilização de comportamento entre objetos. Existem várias diferenças entre a herança prototípica e a baseada em classes. O objetivo dos meus próximos posts é descrever as principais diferenças entre cada uma delas e dar exemplos de situações em que a herança prototípica está presente.

O papel da classe em uma linguagem como o Java é descrever a estrutura e o comportamento de um objeto que será instanciado por ela, além de fornecer um construtor que será utilizado para instanciar esse objeto. A estrutura do objeto instanciado é sua interface, que foi descrita na classe e seu comportamento é determinado pelos métodos que foram implementados na classe.

Em linguagens que usam herança prototípica não existe o conceito de classe, apenas o de objetos e protótipos. Um objeto não tem uma forma estática descrita por uma classe e novos objetos são obtidos a partir da clonagem de um protótipo. Quando se deseja obter um objeto novo, se faz uma cópia de um objeto. Este objeto copiado é que é chamado protótipo. O papel da instanciação do objeto está no seu protótipo, que por acaso, é um objeto também.

Tudo que interessa saber dele em tempo de execução é seu comportamento, quais métodos ele tem. A definição desse comportamento é feita de forma completamente dinãmica. Basicamente, a coisa funciona da seguinte forma: um objeto pode ser imaginado como um amontoado de “coisas”  (objetos e funções/métodos) e essas coisas são guardadas em compartimentos (slots).

Herança prototípica é um conceito que a primeira vista parece muito simples, mas que traz consigo algumas implicações bem interessantes. Por exemplo, todas as informações a respeito de um objeto estão nele, e não comportamento no objeto e descrição/formato na classe. Os protótipos também são mais “contretos” do que classes, porque eles são exemplos do comportamento do objeto ao invés de apenas descrições deles.

Outra coisa bem interessante é que esta forma de herança encoraja a criação de objetos unicamente especializados. Quando utilizamos classes, geralmente estamos descrevendo vários objetos. O que é um problema quando queremos, por exemplo, instanciar apenas um objeto daquela classe. Será que precisamos declarar uma classe que só será usada por um objeto? Ruby e Smalltalk, por exemplo, têm uma classe usada para descrever cada um dos valores booleanos. Já em Self, precisaríamos de dois objetos comuns, o que se comporta como o valor true e outro que se comporta como false. E se eu quiser um objeto que seja só um pouquinho diferente de outro? Preciso usar herança e sobrescrever um método ou adicionar outro? Bom, acho que deu pra entender do que estou falando…

Bom, como já havia dito no inicío do post vou ter que escrever mais outro dia, pra dar citar mais diferenças entre os dois paradigmas e dar mais exemplos em código.  Por enquanto dê uma olhada nesse exemplo em javascript, que não tem nada demais pra quem já conhece a linguagem ou já usou metaprogramação em Ruby, Python ou outra linguagem mais dinâmica, mas que serve como um bom ponto de partida pra quem está totalmente cru no assunto.

/* Objetos em Javascript */

var o = new Object();

o[‘slot1’] = new Object(); // outro objeto

o[‘slot2’] = 1000;

o[‘slot3’] = function() { return this.slot2; } //o ‘this’ da função vai apontar pro escopo do objeto.

Podemos usar a notação literal de objetos para simplificar um pouco isso:

var o = { slot1 : {}, slot2 : 1000, slot3 : funtion() { return this.slot2; }}

É fácil ver que esse estilo de programação encoraja bastante a adição de comportamentos a um objeto em tempo de execução. Por exemplo, seria trivial escrever código para inserir métodos dinâmicamente em um objeto em Javascript:

var entidade = {}

for (nomeAtr in tabelaDoBanco) {

entidade[nomeAtr] = function() {return valorDoAtributo(nomeAtr)};

}

Mas esse exemplo é bastante simplório. No próximo post vou descrever mais detalhadamente as vantagens de desvantagens de linguagens que usam herança prototípica.

Written by Dalto

outubro 20, 2009 às 3:49 am

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: