Polimorfismo
Upcoming SlideShare
Loading in...5
×
 

Polimorfismo

on

  • 987 views

Polimorfismo

Polimorfismo

Statistics

Views

Total Views
987
Views on SlideShare
987
Embed Views
0

Actions

Likes
1
Downloads
8
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Polimorfismo Polimorfismo Document Transcript

  • O que é Polimorfismo?Jacques Philippe SauvéMuitos livros de programação falam de polimorfismo de forma equivocada. Até a famosa MonicaPawlan pisou na bola, em minha opinião. Ela dá a impressão que o polimorfismo ocorre quandopassamos objetos como parâmetros numa chamada de método, o que não é verdade. Ela também dáa impressão que o polimorfismo deve envolver uma superclasse, o que também não é verdade.Outros autores famosos cometem os mesmos erros (Os autores de Core Java, por exemplo).Então vamos tentar enxergar o que é polimorfismo. Na realidade, é bastante simples,conceitualmente, embora os detalhes tenham um jeito de obscurecer a situação.De forma genérica, polimorfismo significa "várias formas". Numa linguagem de programação, issosignifica que pode haver várias formas de fazer uma "certa coisa". Aí vem a primeira coisaimportante: que "certa coisa" é essa? A resposta é que estamos falando de chamadas de métodos.Portanto, em Java, o polimorfismo se manifesta apenas em chamadas de métodos. Agora, podemosser mais específicos sobre a definição de polimorfismo: Polimorfismo significa que uma chamadade método pode ser executada de várias formas (ou polimorficamente). Quem decide "a forma" é oobjeto que recebe a chamada. Essa última frase é muito importante, pois ela encerra a essência dopolimorfismo. Leia a frase novamente.Ela significa o seguinte: Se um objeto "a" chama um método xpto() de um objeto "b", então oobjeto "b" decide a forma de implementação do método. Mais especificamente ainda, é o tipo doobjeto "b" que importa. Para concretizar melhor, digamos que xpto() seja grita(). Então a chamadab.grita() vai ser um grito humano se "b" for um humano e será um grito de macaco, se o objeto "b"for um macaco. O que importa, portanto, é o tipo do objeto receptor "b".Podemos agora resolver uma das confusões de Monica Pawlan. O objeto "a" possui uma referênciapara o objeto "b", obviamente, já que ele está chamando o método grita() do objeto "b". Isto é, eleexecuta b.grita(). De onde veio essa referência ao objeto "b"? Monica Pawlan diz que ela foirecebida como parâmetro pelo objeto "a" em alguma chamada de método. Não tem nada a ver.Tanto faz como "a" recebeu a referência a "b". Pode ter sido como Pawlan falou ou pode ser devárias outras formas. Vamos dar alguns exemplos:1. O objeto "a" cria o objeto "b"class A { void facaAlgo() { Gritador b; if(...) { b = new Humano(); } else { b = new Macaco(); } b.grita(); // chamada polimórfica }}2. O objeto "a" recebe o objeto "b" de um objeto "c"class A { void facaAlgo() { Gritador b = c.meDeUmGritador(); // "c" é um objeto qualquer para o qual tenhoreferência b.grita(); // chamada polimórfica
  • }}3. O objeto "a" recebe o objeto "b" numa chamada de métodoclass A { void facaAlgo(Gritador b) { b.grita(); // chamada polimórfica }}O que Monica Pawlan falou é a forma 3. Tem outras formas ainda de obter essa referência. Oimportante é que "a" tem uma referência a "b" e pronto. Não importa de onde ela vem.Então onde ocorre o polimorfismo na linguagem Java? Resposta: nas chamadas de métodos. Agorapodemos perguntar: há polimorfismo nas chamadas de quais métodos? Resposta: EmJava, todas as chamadas de métodos a objetos são polimórficas. Se você observar bem a últimafrase, você vai observar duas coisas: 1. Estou falando de Java. Em algumas outras linguagens, como C++, você pode especificar quais métodos são polimórficos e quais não são. 2. Voltando a Java, estou falando de "métodos de objetos". Isso significa que, em Java, não há polimorfismo ao chamar métodos estáticos (também chamados de "métodos de classes"). Porém, métodos de objetos sempre são polimórficos.Tudo que tem acima deve ser mais ou menos simples. A complicação começa agora. Não é tãocomplicado assim, mas é o suficientepara ter atrapalhado muitos autores de livros. Temos que falar de tipos.Não é qualquer objeto que pode gritar, certo? Se eu tiver um objeto "b" representando uma cadeirae fizer b.grita(), não pode sair coisa boa, porque uma cadeira não grita. Temos, portanto queindicar, de alguma forma, o tipo de objeto que pode ser usado neste lugar. Fazemos isso usandotipos. Você viu, acima, que a referência "b" é do tipo "Gritador". O que é Gritador? Na realidade,para o compilador Java, não importa o que seja Gritador, desde que este tipo saiba gritar, isto é,Gritador é qualquer coisa que tenha um método grita().Aí está à confusão da maioria dos livros de programação O-O. Eles dizem que Gritador é umasuperclasse e é isso que causa o polimorfismo. Não é verdade. Há duas formas básicas de criar umtipo em Java e ambas as formas podem ser usadas para definir Gritador. Uma forma de definir umtipo (a mais correta, para mim) é assim:interface Gritador { void grita();}Esse é um tipo chamado "tipo abstrato" porque só dizemos que existe um método grita() sem dizernada sobre sua implementação. Isto é, como gritar não foi especificado. Agora, posso fazer comque qualquer classe implemente este tipo. Veja abaixo:class Humano implements Gritador { public void grita() { System.out.println("AAAAAAHHHHHHHAAAAHHHHHHAAAAAHHHHHA"); // Me Tarzan! }}class Macaco implements Gritador { public void grita() {
  • System.out.println("IIIIIIIIHHHHHHHIIIIHHHHHHIIIIIIHHHHHI"); // Me Cheetah! }}As duas classes implementam o tipo Gritador e as chamadas polimórficas que mostrei mais acimafuncionarão sem problemas. Observe que não há superclasse envolvida! Não é necessário ter umahierarquia de classes para ter polimorfismo, embora quase todos os autores de livros apresentempolimorfismo usando hierarquias de classes. O importante é: qualquer objeto que implementa otipo Gritador poderá ser usado nos exemplos que mostrei acima onde o objeto "a" quer tratar comum gritador. Se, amanhã, eu criar uma nova classe:class Aluno implements Gritador { public void grita() { System.out.println("naoquerofazerprovanaoquerofazerprovanaoquerofazerprova"); // MeJoãozinho! }}Então objetos dessa classe funcionarão nos exemplos anteriores na chamada b.grita().Observe que, se eu tiver um programa com objetos das classes Humano, Macaco e Aluno, terei 3implementações diferentes do método grita(). A chamada b.grita() está chamando um desses trêsmétodos, dependendo da classe do objeto "b". Achar o método correto a ser chamado para umobjeto particular chama-se dynamic binding, ou amarração dinâmica. Isto é, temos que amarrar achamada b.grita() a uma das implementações de grita() dinamicamente, em tempo de execução (enão em tempo de compilação, o que se chamaria static binding).Agora, vamos logo para a confusão. A herança também permite fazer polimorfismo porque aherança permite criar várias classes que implementam o mesmo tipo. Lembre que se eu tiver váriasclasses implementando o mesmo tipo, posso fazer polimorfismo (várias classes implementandoGritador, por exemplo). Agora, ao definir uma classe:class UmGritador { public grita() { System.out.println("Buuuuu"); }}eu também estou criando um tipo. Só que desta vez, ele não é abstrato. O tipo UmGritador é umtipo concreto porque ele fornece uma implementação concreta do método grita(). Porém,UmGritador não deixa de ser um tipo (ele é um tipo e a implementação deste tipo). Sendo assim, oque ocorre quando uso herança? Veja:class Humano extends UmGritador { public void grita() { System.out.println("AAAAAAHHHHHHHAAAAHHHHHHAAAAAHHHHHA"); }}Olhe o "extends" acima: estou fazendo herança. Ao fazer herança, objetos da classe Humano vãoherdar todos os métodos da superclasse UmGritador. Isto significa que, com herança, vou herdar otipo da superclasse e também a implementação da superclasse. O polimorfismo vem agora. Presteatenção. Ao herdar, a subclasse pode fazer override (substituir) alguns métodos. É isso queHumano fez, acima: ele decidiu gritar de forma diferente. Isso significa que objetos da classeUmGritador, ou da classe Humano ou da classe Macaco terão formas diferentes de implementargritar(). Portanto, haverá polimorfismo ao chamara b.gritar()
  • Vou pegar um exemplo anterior e alterar só o tipo na definição do objeto "b":class A { void facaAlgo() { UmGritador b; if(...) { b = new Humano(); } else { b = new Macaco(); } b.grita(); // chamada polimórfica }}Agora, o tipo é uma superclasse e não um tipo abstrato (interface). Terei polimorfismo, sim, porquetenho vários objetos que implementam o mesmo tipo e que possuem implementações diferentes dométodo gritar(). Posso fazer isso com herança ou posso fazer isso sem herança. A confusão demuitos autores de livros é que eles apresentam polimorfismo com herança, dando a impressãoque tem que ter herança para ter polimorfismo.Eu prefiro apresentar polimorfismo com tipos abstratos (interface, em Java), para deixar claro quepolimorfismo é uma coisa, herança é outra (embora haja ligação).Espero que tudo isso não esteja te deixando mais confuso!Agora, vamos terminar a discussão dizendo: para fazer polimorfismo, é melhor usar tipos abstratosou tipos concretos (herança)? Nem todo mundo concorda com a melhor forma de fazer isso. Minhaopinião é:  Use tipos abstratos (interface) para fazer polimorfismo  Use herança para fatorar código comum entre várias classesEm outras palavras:  Defina comportamentos ("ser um gritador") com tipos abstratos (interfaces) e use-os no polimorfismo  Defina implementações (como gritar) com classes e use superclasses para fatorar implementações comuns.Espero ter ajudado.Jacques