Sei sulla pagina 1di 8

Programao Orientada a Objetos

Polimorfismo e Acoplamento Dinmico


Neste captulo so apresentados os conceitos de polimorfismo, linguagens monomrficas e polimrficas, a classificao de polimorfismo de Cardelli e Wegner e acoplamento dinmico. descrita tambm a forma de encaminhamento de mensagem de Java. Ao final deste captulo o estudante dever ser capaz de distinguir as vrias modalidades de polimorfismo e empreg-las corretamente em Java. 1. Conceito de Polimorfismo O dicionrio Aurlio nos oferece as seguintes definies: Polimorfo: que se apresenta sob numerosas formas; multiforme; sujeito a variar de forma. Polimorfismo: em botnica, polimorfismo foliar significa que um vegetal apresenta folhas de vrios tipos morfolgicos. O conceito original de polimorfismo em programao atribudo a Strachey [Stratchey67], quando diz: Polimorfismo universal ou polimorfismo verdadeiro (true polymorphism) "Temos polimorfismo universal quando uma funo trabalha uniformemente para uma gama de tipos; tipos esses normalmente com uma estrutura uniforme." Polimorfismo ad hoc (ad bhoc polymorphism) ou polimorfismo aparente (apparent polymorphism) "Temos polimorfismo ad-hoc quando uma funo trabalha, ou parece trabalhar, para vrios tipos diferentes (que podem no ter estruturas semelhantes) e pode se comportar de formas diferentes para cada tipo." Um exemplo clssico de polimorfismo o de uma funo sort(), capaz de ordenar uma lista de itens de um tipo qualquer, sejam nmeros inteiros, nmeros reais ou cadeias de caracteres, por exemplo. O cdigo seguinte mostra como essa funo poderia ser utilizada:
int i[100]; float x[200]; char* s[50]; sort(i,100); // classifica vetor com 100 inteiros sort(x,200); // classifica vetor com 200 reais sort(s,50); // classifica vetor com 50 strings

Uma funo C ou Pascal, por exemplo, exige que os tipos dos parmetros sejam especificados na definio da funo, no sendo possvel definir uma funo verdadeiramente polimrfica como acima, onde o tipo de um parmetro permanea indefinido at o momento da compilao do programa. A funo qsort() de C implementa algo parecido com a funo acima descrita, produzindo um polimorfismo apenas aparente. Um dos parmetros de qsort() uma funo de comparao que depende do tipo de dado contido na lista, a ser executada atravs de um mecanismo de call-back. Existiro, portanto, diferentes implementaes para aquela parte da funo qsort() que dependente do tipo de dado contido na lista. 2. Polimorfismo e Orientao a Objetos Podemos sintetizar o conceito de polimorfismo, estendendo-o para a terminologia de orientao a objetos, como:

Programao Orientada a Objetos

Polimorfismo (polymorphism) o efeito produzido por uma funo (ou mtodo) capaz de operar para uma variedade de tipos de dados (ou classes de objetos). Nas linguagens orientadas a objetos o efeito de polimorfismo est intimamente associado aos conceitos de tipo abstrato de dados e de herana. Nessas linguagens uma varivel definida como uma referncia para um objeto de uma classe C1 pode, durante a execuo do programa, referenciar tanto objetos dessa classe como de qualquer classe C2 descendente de C1. Essa propriedade as caracteriza como linguagens polimrficas [Cardelli85] em contraste com as linguagens ditas monomrficas, como C ou Pascal. Linguagem Monomrfica (monomorphic language) Cada valor ou varivel s pode ser interpretado como sendo de um nico tipo. Linguagem Polimrfica (polymorphic language) Alguns valores ou variveis podem ser interpretados como sendo de mais de um tipo. Como C2 herda todas as operaes de C1, os mtodos de C1, assim como todo mtodo que tenha como parmetro um objeto da classe C1, iro funcionar uniformemente para objetos tanto de C1 como de C2. Sero, portanto, naturalmente polimrficos. 3. Classificao de Cardelli e Wegner Cardelli e Wegner ] estendem aquela classificao inicial de polimorfismo de Strachey, para abranger as modalidades de polimorfismo tpicas das linguagens orientadas a objetos, da seguinte forma: Polimorfismo / \ _ Universal _ __ Ad Hoc _ / \ / \ Paramtrico Incluso Sobrecarga Coero No polimorfismo universal um mesmo mtodo (ou funo) pode ser executado para um conjunto possivelmente ilimitado de tipos de dados diferentes. J no polimorfismo "ad hoc" um mesmo mtodo s pode ser executado para um conjunto limitado de tipos de dados, definidos estaticamente. 3.1. Sobrecarga de Mtodos e Operadores

Sobrecarga de Mtodos e Construtores Ocorre quando existem dois ou mais mtodos de mesmo nome, que realizam operaes similares, para objetos de diferentes tipos. Um exemplo de sobrecarga em Java o mtodo intValue(), que converte o valor armazenado num objeto para um valor do tipo int. Esse mtodo implementado nas classes Byte, Double, Float, Integer, Long, Number e Short, o que faz com que a expresso x.intValue() funcione uniformemente para qualquer objeto x de uma dessas classes. Outro exemplo de sobrecarga de mtodos freqente em Java quando temos vrios mtodos construtores para uma classe, com diferentes assinaturas. Na classe String, por exemplo, dentre cerca de dez diferentes construtores, temos:
public String(String value); public String(char value[]); public String(byte bytes[]);

Desta forma o comando new String(x) funciona uniformemente para qualquer objeto x de uma das classes String, char[] ou byte[].

Programao Orientada a Objetos

Observe que h um nico mtodo intValue() ou um nico construtor String(), verdadeiramente polimrficos. Para cada forma de chamada possvel h uma implementao especfica do mtodo. a uniformidade de chamada desses mtodos, por possurem assinaturas parecidas (ou idnticas), que produz o efeito de polimorfismo. No h, no entanto, nenhuma garantia, alm de uma conveno arbitrria, de que essas diferentes implementaes realizam operaes semanticamente equivalentes. Sobrecarga de Operadores Ocorre quando um operador da linguagem pode ter diferentes significados, dependendo do tipo do operando ao qual aplicado. Por exemplo: na expresso a+=b o operador += significa, normalmente, "adicione o valor de b ao atributo a". Atravs de uma sobrecarga esse operador poderia adquirir novos significados, como "inclua o elemento b no conjunto a", ou qualquer outro desejado, dependendo da implementao dos tipos a e b. Algumas linguagens orientadas a objetos, como C++, permitem esse tipo de sobrecarga. Como esse recurso pode obscurecer o cdigo do programa, dificultando sua manuteno, no foi includo na linguagem Java. 3.2. Coero Java, assim como outras linguagens de programao, define uma hierarquia entre seus tipos de dados nativos, como por exemplo: nmeros inteiros so um subtipo de nmeros reais. Se um particular contexto demanda um determinado tipo de dado e fornecido um valor de outro tipo, porm da mesma hierarquia, o compilador faz uma converso automtica para o tipo exigido, portanto que o tipo exigido seja supertipo do tipo do valor fornecido. o caso, por exemplo, de uma chamada ao mtodo debitaValor em que fornecemos o valor a debitar atravs de uma varivel de tipo int, em lugar de uma varivel de tipo float, como definido na assinatura do mtodo. O valor inteiro automaticamente promovido a um dado do tipo float, antes da chamada do mtodo. Em Java so executadas implicitamente as seguintes converses sobre valores de tipos primitivos fornecidos como argumentos para chamadas de mtodos:
byte to short, int, long, float, or double short to int, long, float, or double char to int, long, float, or double int to long, float, or double long to float or double float to double

Todas essas converses so promoes de tipo (widening conversions) o dado inicial de um tipo cujo domnio est contido no domnio do tipo resultante. No pode haver, portanto, truncamento no resultado. A converso entre tipos inteiros (short, int ou long) e reais (float ou double) pode, no entanto, resultar em perda de preciso. O programa seguinte permite observarmos algumas dessas converses automticas.

Programao Orientada a Objetos Class Cap8c { static public void main (String Arg[]) { MinhaClasse o=new MinhaClasse(); short s1=1, s2=2; int i1=3, i2=4; long l1=5, l2=6; o.metodo(s1,s2); // no h converso -> 1o. mtodo o.metodo(s1,i2); // s1 para int -> 2o. mtodo o.metodo(s1,l2); // s1 para long -> 3o. mtodo o.metodo(i1,i2); // no h converso -> 2o. mtodo o.metodo(i1,l2); // i1 para long -> 3o. mtodo o.metodo(l1,s2); // s2 para long -> 3o. mtodo o.metodo(l1,l2); // no h converso -> 3o. mtodo } } class MinhaClasse { void metodo (short i, short j) { System.out.println("metodo1 - i="+i+" j="+j); } void metodo (int i, int j) { System.out.println("metodo2 - i="+i+" j="+j); } void metodo (long i, long j) { System.out.println("metodo3 - i="+i+" j="+j); } }

Note que o exemplo acima ilustra tambm a sobrecarga de mtodos, com trs mtodos de mesmo nome, porm com diferentes assinaturas e implementaes. Os resultados obtidos na execuo desse programa so:
metodo1 metodo2 metodo3 metodo2 metodo3 metodo3 metodo3 i=1 i=1 i=1 i=3 i=3 i=5 i=5 j=2 j=4 j=6 j=4 j=6 j=2 j=6

Converses no sentido inverso ou rebaixamento de tipo (narrowing conversions), onde pode ocorrer truncamento do resultado, s so executadas quando especificadas explicitamente pelo programador, como na linha abaixo:
o.metodo((int)l1,(int)l2); // converso explcita -> 2o. mtodo

Essa modalidade de polimorfismo reduz a legibilidade do programa, propiciando a ocorrncia de erros de programao. Deve-se, portanto, evitar a definio de mtodos com assinaturas parecidas, como no exemplo acima, e, quando necessrio, explicitar as converses de tipo adequadas em cada caso. 3.3. Polimorfismo Paramtrico Nessa modalidade de polimorfismo universal, o tipo de dado a ser tratado um dos parmetros do mtodo ou funo. Algumas linguagens, como C++, permitem definir templates de funes, usando tipos de dados como parmetros, como no exemplo seguinte:
template <class T> void troca(T& a, T& b) { T temp = a; a = b; b = temp; }

A funo troca() definida como tendo dois parmetros (a e b), que devem ser de um mesmo tipo T. A varivel auxiliar temp definida como sendo do tipo T. Observe que, alm de funcionar uniformemente para qualquer tipo de parmetro, o faz sempre conforme

Programao Orientada a Objetos

uma nica implementao. Java no oferece um mecanismo generalizado para definio de mtodos paramtricos. Um exemplo desse tipo de polimorfismo em Java, porm, a definio de vetores e matrizes (arrays). O tipo array um tipo pr-definido de Java, assim como os tipos int e char. Um objeto de tipo array possui um conjunto de operaes caractersticas, tais como: x.length - obtm o nmero m de elementos armazenados em x; x[int i] - obtm o endereo do i-simo elemento armazenado em x. A implementao dessas operaes, porm, depende do tipo de valor armazenado no array. Considere as seguintes definies Java, onde so criados dois objetos de tipo array (cc e x), o primeiro para armazenar referncias de objetos do tipo ContaCor e o segundo para armazenar caracteres:
ContaCor cc[]; char x[];

Note que o tipo array declarado atravs dos smbolos []. Os tipos ContaCor e char funcionam como parmetros para a construo do array. 3.4. Polimorfismo de Incluso O polimorfismo de incluso est relacionado ao conceito de subtipo. Ele permite que tratemos objetos de diferentes tipos de uma maneira uniforme, desde que haja um supertipo comum a todos que defina as operaes que sero usadas a partir de instncias dos subtipos. A definio de hierarquias de tipos favorece a utilizao dessa modalidade de polimorfismo, pois os mtodos herdados pelas subclasses tornam-se, automaticamente, polimrficos. Os mtodos da classe Object, que a raiz de todas as hierarquias de classes Java, so tambm exemplos dessa modalidade de polimorfismo, pois so capazes de operar uniformemente sobre objetos de qualquer tipo. Redefinio de Mtodos um caso especial de polimorfismo de incluso que ocorre quando uma subclasse define uma forma de implementao especializada, para um mtodo herdado da superclasse. Redefinio versus Sobrecarga de Mtodos Para que ocorra uma redefinio de mtodo, necessrio que o novo mtodo possua assinatura idntica de um mtodo herdado pela classe que ser redefinido. O mtodo da subclasse e o mtodo herdado devem coincidir quanto ao tipo de resultado, ao nome e lista de parmetros (mesmo nmero de parmetros, de mesmos tipos e na mesma ordem). No havendo essa coincidncia de assinaturas entre um mtodo herdado e um mtodo definido na subclasse, mas apenas uma coincidncia entre nomes de mtodos, o que ocorre apenas uma sobrecarga de mtodos, como definido na seo 8.3.1. importante ressaltar que, neste ltimo caso, os tipos de resultado dos mtodos podem ser diferentes apenas se houverem diferenas tambm nas listas de parmetros. 4. Acoplamento Dinmico e Redefinio de Mtodos A implementao de operaes polimrficas implica em situaes onde a determinao de qual mtodo deve ser executado para uma determinada chamada s pode ser feita no momento da chamada.

Programao Orientada a Objetos

Seja, por exemplo, uma chamada ao mtodo debitaValor(), definido na classe ContaCor e redefinido na classe ContaEsp. Na seqncia abaixo, o mtodo a ser chamado por c1.debitaValor() s pode ser decidido no exato momento em que o comando for executado, j que c1 pode estar referenciando tanto um objeto da classe ContaCor quanto da classe ContaEsp:
ContaCor c1; // c1 pode referenciar objetos de ContaCor // ou de suas subclasses, como ContaEsp ... c1=new ContaCor(...); // c1 -> objeto de ContaCor c2=new ContaEsp(...); // c2 -> objeto de ContaEsp ... if (...) c1=c2; // se ... c1 -> objeto de ContaEsp c1.debitaValor(...) // c1 -> ? ContaCor ou ContaEsp ?

A esse tipo de ligao entre subprogramas chamamos de acoplamento dinmico ou tardio (dynamic binding ou late binding). Em linguagens monomrficas, como Pascal ou C, o acoplamento sempre esttico (static binding ou early binding), ou seja, todas as ligaes entre os subprogramas so estabelecidas antes da execuo do programa, normalmente durante a compilao ou ligao (linkage), e permanecem inalteradas durante todo o tempo de execuo do programa. A forma de resoluo de uma chamada com acoplamento dinmico depende da linguagem de programao utilizada, podendo haver tanto diferenas semnticas, quanto ao mtodo (ou mtodos) a ser chamado, como diferenas de desempenho, por exemplo. o mecanismo de encaminhamento de mensagens da linguagem que determina essa forma. 8.5. Encaminhamento das Mensagens em Java Em Java, assim como em C++ e outras linguagens mais populares, o encaminhamento das mensagens feito no sentido "de baixo para cima", ou seja, da classe do objeto que recebe a mensagem para sua superclasse e assim sucessivamente. Caso a classe de um objeto defina (ou redefina) um mtodo capaz de tratar uma mensagem, a mensagem entregue imediatamente. Caso contrrio, a mensagem entregue classe ancestral mais prxima que defina (ou redefina) um mtodo capaz de processar a mensagem. A figura 8.5 ilustra a situao da memria do programa aps a instanciao de um objeto da classe ContaEsp e a recepo de uma mensagem pelo objeto. A rea hachurada ao p do diagrama destaca a parte da representao do objeto que estende a representao de um objeto da superclasse. Os mtodos da superclasse simplesmente ignoram essa extenso. Quando o objeto recebe uma mensagem (1) inicia-se a busca por um mtodo que possa trata-la na definio da classe ContaEsp (2), que a classe do objeto. Caso seja encontrado um mtodo com assinatura compatvel com a mensagem, esse mtodo executado. Caso contrrio, a busca prossegue, agora na definio da classe ContaCor (3), que a classe ancestral mais prxima, e assim sucessivamente at que seja encontrado um mtodo apropriado para tratar a mensagem.
ght 2003, Ceclia Rubira. Todos os direitos reservados.

Programao Orientada a Objetos

Cap. 8 / Polimorfismo e Acoplamento Dinmico

75

Fig. 8.5 Instanciao de Objeto da Subclasse

8.6. Exerccios de Fixao

Copyright 2003, Ceclia Rubira. Todos os direitos reservados.

Programao Orientada a Objetos

Potrebbero piacerti anche