SlideShare una empresa de Scribd logo
1 de 4
Descargar para leer sin conexión
O que é Polimorfismo?
Jacques Philippe Sauvé

Muitos livros de programação falam de polimorfismo de forma equivocada. Até a famosa Monica
Pawlan pisou na bola, em minha opinião. Ela dá a impressão que o polimorfismo ocorre quando
passamos 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, isso
significa que pode haver várias formas de fazer uma "certa coisa". Aí vem a primeira coisa
importante: 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, podemos
ser mais específicos sobre a definição de polimorfismo: Polimorfismo significa que uma chamada
de método pode ser executada de várias formas (ou polimorficamente). Quem decide "a forma" é o
objeto que recebe a chamada. Essa última frase é muito importante, pois ela encerra a essência do
polimorfismo. Leia a frase novamente.
Ela significa o seguinte: Se um objeto "a" chama um método xpto() de um objeto "b", então o
objeto "b" decide a forma de implementação do método. Mais especificamente ainda, é o tipo do
objeto "b" que importa. Para concretizar melhor, digamos que xpto() seja grita(). Então a chamada
b.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ência
para o objeto "b", obviamente, já que ele está chamando o método grita() do objeto "b". Isto é, ele
executa b.grita(). De onde veio essa referência ao objeto "b"? Monica Pawlan diz que ela foi
recebida 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 de
vá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 tenho
referência
    b.grita(); // chamada polimórfica
}
}

3. O objeto "a" recebe o objeto "b" numa chamada de método
class 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. O
importante é 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. Agora
podemos perguntar: há polimorfismo nas chamadas de quais métodos? Resposta: Em
Java, todas as chamadas de métodos a objetos são polimórficas. Se você observar bem a última
frase, 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ão
complicado assim, mas é o suficiente
para 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 cadeira
e fizer b.grita(), não pode sair coisa boa, porque uma cadeira não grita. Temos, portanto que
indicar, de alguma forma, o tipo de objeto que pode ser usado neste lugar. Fazemos isso usando
tipos. 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 é uma
superclasse e é isso que causa o polimorfismo. Não é verdade. Há duas formas básicas de criar um
tipo em Java e ambas as formas podem ser usadas para definir Gritador. Uma forma de definir um
tipo (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 dizer
nada sobre sua implementação. Isto é, como gritar não foi especificado. Agora, posso fazer com
que 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 acima
funcionarão sem problemas. Observe que não há superclasse envolvida! Não é necessário ter uma
hierarquia de classes para ter polimorfismo, embora quase todos os autores de livros apresentem
polimorfismo usando hierarquias de classes. O importante é: qualquer objeto que implementa o
tipo Gritador poderá ser usado nos exemplos que mostrei acima onde o objeto "a" quer tratar com
um gritador. Se, amanhã, eu criar uma nova classe:
class Aluno implements Gritador {
  public void grita() {
    System.out.println("naoquerofazerprovanaoquerofazerprovanaoquerofazerprova"); // Me
Joã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 3
implementações diferentes do método grita(). A chamada b.grita() está chamando um desses três
métodos, dependendo da classe do objeto "b". Achar o método correto a ser chamado para um
objeto particular chama-se dynamic binding, ou amarração dinâmica. Isto é, temos que amarrar a
chamada b.grita() a uma das implementações de grita() dinamicamente, em tempo de execução (e
nã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 a
herança permite criar várias classes que implementam o mesmo tipo. Lembre que se eu tiver várias
classes implementando o mesmo tipo, posso fazer polimorfismo (várias classes implementando
Gritador, 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 é um
tipo 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, o
que 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ão
herdar todos os métodos da superclasse UmGritador. Isto significa que, com herança, vou herdar o
tipo da superclasse e também a implementação da superclasse. O polimorfismo vem agora. Preste
atenção. Ao herdar, a subclasse pode fazer override (substituir) alguns métodos. É isso que
Humano fez, acima: ele decidiu gritar de forma diferente. Isso significa que objetos da classe
UmGritador, ou da classe Humano ou da classe Macaco terão formas diferentes de implementar
gritar(). 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, porque
tenho vários objetos que implementam o mesmo tipo e que possuem implementações diferentes do
método gritar(). Posso fazer isso com herança ou posso fazer isso sem herança. A confusão de
muitos autores de livros é que eles apresentam polimorfismo com herança, dando a impressão
que tem que ter herança para ter polimorfismo.
Eu prefiro apresentar polimorfismo com tipos abstratos (interface, em Java), para deixar claro que
polimorfismo é 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 abstratos
ou tipos concretos (herança)? Nem todo mundo concorda com a melhor forma de fazer isso. Minha
opinião é:

      Use tipos abstratos (interface) para fazer polimorfismo
      Use herança para fatorar código comum entre várias classes

Em 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

Más contenido relacionado

Destacado

Destacado (17)

Sintaxe Portugus 090516070420 Phpapp02
Sintaxe Portugus 090516070420 Phpapp02Sintaxe Portugus 090516070420 Phpapp02
Sintaxe Portugus 090516070420 Phpapp02
 
RELAT
RELATRELAT
RELAT
 
Mandeep CV update
Mandeep CV updateMandeep CV update
Mandeep CV update
 
Presentado por juan atencia
Presentado por juan atenciaPresentado por juan atencia
Presentado por juan atencia
 
Archivo22 0
Archivo22 0Archivo22 0
Archivo22 0
 
Trabalho De Web
Trabalho De WebTrabalho De Web
Trabalho De Web
 
Estatísticas
EstatísticasEstatísticas
Estatísticas
 
Glosario de microeconomia
Glosario de microeconomiaGlosario de microeconomia
Glosario de microeconomia
 
Libro ElectróNico (Miguel, Catherine)
Libro ElectróNico (Miguel, Catherine)Libro ElectróNico (Miguel, Catherine)
Libro ElectróNico (Miguel, Catherine)
 
Relatório de 2º período
Relatório de 2º períodoRelatório de 2º período
Relatório de 2º período
 
Ronald Sangster Reference
Ronald Sangster ReferenceRonald Sangster Reference
Ronald Sangster Reference
 
A Verdadeira Beleza
A Verdadeira BelezaA Verdadeira Beleza
A Verdadeira Beleza
 
2010 10-16 workshop gestão de projetos 2010 - palestra gestão de tempo de g...
2010 10-16 workshop gestão de projetos 2010 - palestra gestão de tempo de g...2010 10-16 workshop gestão de projetos 2010 - palestra gestão de tempo de g...
2010 10-16 workshop gestão de projetos 2010 - palestra gestão de tempo de g...
 
XVI Foro del Futuro: Juan Manuel Barragán
XVI Foro del Futuro: Juan Manuel BarragánXVI Foro del Futuro: Juan Manuel Barragán
XVI Foro del Futuro: Juan Manuel Barragán
 
2º seminario tic laura arriaza granado 1
2º seminario tic laura arriaza granado 12º seminario tic laura arriaza granado 1
2º seminario tic laura arriaza granado 1
 
Para slide
Para slidePara slide
Para slide
 
Fotos
FotosFotos
Fotos
 

Similar a Polimorfismo

Similar a Polimorfismo (15)

Curso
CursoCurso
Curso
 
Fugindo para as colinas com Python - Julio Biason - Tchelinux Bento Gonçalves...
Fugindo para as colinas com Python - Julio Biason - Tchelinux Bento Gonçalves...Fugindo para as colinas com Python - Julio Biason - Tchelinux Bento Gonçalves...
Fugindo para as colinas com Python - Julio Biason - Tchelinux Bento Gonçalves...
 
03 - Orientação a objetos e classes em C# v1.0
03 - Orientação a objetos e classes em C# v1.003 - Orientação a objetos e classes em C# v1.0
03 - Orientação a objetos e classes em C# v1.0
 
C#4 – O que há de novo
C#4 – O que há de novoC#4 – O que há de novo
C#4 – O que há de novo
 
02 - Orientação a objetos e revisão de C# v1.5
02 - Orientação a objetos e revisão de C# v1.502 - Orientação a objetos e revisão de C# v1.5
02 - Orientação a objetos e revisão de C# v1.5
 
Virada Tecnológica 2017
Virada Tecnológica 2017Virada Tecnológica 2017
Virada Tecnológica 2017
 
05 poo-ii
05   poo-ii05   poo-ii
05 poo-ii
 
Fj pratica04
Fj pratica04Fj pratica04
Fj pratica04
 
Classes abstratas
Classes abstratasClasses abstratas
Classes abstratas
 
Semanaupecaruaru2013 c++para iniciantes
Semanaupecaruaru2013 c++para iniciantesSemanaupecaruaru2013 c++para iniciantes
Semanaupecaruaru2013 c++para iniciantes
 
Java7
Java7Java7
Java7
 
Python bge
Python bgePython bge
Python bge
 
ebook-completo c# o melhor para começar no c#
ebook-completo c# o melhor para começar no c#ebook-completo c# o melhor para começar no c#
ebook-completo c# o melhor para começar no c#
 
Classes objetos
Classes objetosClasses objetos
Classes objetos
 
Ruby versus Python
Ruby versus PythonRuby versus Python
Ruby versus Python
 

Polimorfismo

  • 1. O que é Polimorfismo? Jacques Philippe Sauvé Muitos livros de programação falam de polimorfismo de forma equivocada. Até a famosa Monica Pawlan pisou na bola, em minha opinião. Ela dá a impressão que o polimorfismo ocorre quando passamos 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, isso significa que pode haver várias formas de fazer uma "certa coisa". Aí vem a primeira coisa importante: 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, podemos ser mais específicos sobre a definição de polimorfismo: Polimorfismo significa que uma chamada de método pode ser executada de várias formas (ou polimorficamente). Quem decide "a forma" é o objeto que recebe a chamada. Essa última frase é muito importante, pois ela encerra a essência do polimorfismo. Leia a frase novamente. Ela significa o seguinte: Se um objeto "a" chama um método xpto() de um objeto "b", então o objeto "b" decide a forma de implementação do método. Mais especificamente ainda, é o tipo do objeto "b" que importa. Para concretizar melhor, digamos que xpto() seja grita(). Então a chamada b.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ência para o objeto "b", obviamente, já que ele está chamando o método grita() do objeto "b". Isto é, ele executa b.grita(). De onde veio essa referência ao objeto "b"? Monica Pawlan diz que ela foi recebida 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 de vá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 tenho referência b.grita(); // chamada polimórfica
  • 2. } } 3. O objeto "a" recebe o objeto "b" numa chamada de método class 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. O importante é 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. Agora podemos perguntar: há polimorfismo nas chamadas de quais métodos? Resposta: Em Java, todas as chamadas de métodos a objetos são polimórficas. Se você observar bem a última frase, 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ão complicado assim, mas é o suficiente para 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 cadeira e fizer b.grita(), não pode sair coisa boa, porque uma cadeira não grita. Temos, portanto que indicar, de alguma forma, o tipo de objeto que pode ser usado neste lugar. Fazemos isso usando tipos. 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 é uma superclasse e é isso que causa o polimorfismo. Não é verdade. Há duas formas básicas de criar um tipo em Java e ambas as formas podem ser usadas para definir Gritador. Uma forma de definir um tipo (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 dizer nada sobre sua implementação. Isto é, como gritar não foi especificado. Agora, posso fazer com que 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() {
  • 3. System.out.println("IIIIIIIIHHHHHHHIIIIHHHHHHIIIIIIHHHHHI"); // Me Cheetah! } } As duas classes implementam o tipo Gritador e as chamadas polimórficas que mostrei mais acima funcionarão sem problemas. Observe que não há superclasse envolvida! Não é necessário ter uma hierarquia de classes para ter polimorfismo, embora quase todos os autores de livros apresentem polimorfismo usando hierarquias de classes. O importante é: qualquer objeto que implementa o tipo Gritador poderá ser usado nos exemplos que mostrei acima onde o objeto "a" quer tratar com um gritador. Se, amanhã, eu criar uma nova classe: class Aluno implements Gritador { public void grita() { System.out.println("naoquerofazerprovanaoquerofazerprovanaoquerofazerprova"); // Me Joã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 3 implementações diferentes do método grita(). A chamada b.grita() está chamando um desses três métodos, dependendo da classe do objeto "b". Achar o método correto a ser chamado para um objeto particular chama-se dynamic binding, ou amarração dinâmica. Isto é, temos que amarrar a chamada b.grita() a uma das implementações de grita() dinamicamente, em tempo de execução (e nã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 a herança permite criar várias classes que implementam o mesmo tipo. Lembre que se eu tiver várias classes implementando o mesmo tipo, posso fazer polimorfismo (várias classes implementando Gritador, 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 é um tipo 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, o que 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ão herdar todos os métodos da superclasse UmGritador. Isto significa que, com herança, vou herdar o tipo da superclasse e também a implementação da superclasse. O polimorfismo vem agora. Preste atenção. Ao herdar, a subclasse pode fazer override (substituir) alguns métodos. É isso que Humano fez, acima: ele decidiu gritar de forma diferente. Isso significa que objetos da classe UmGritador, ou da classe Humano ou da classe Macaco terão formas diferentes de implementar gritar(). Portanto, haverá polimorfismo ao chamara b.gritar()
  • 4. 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, porque tenho vários objetos que implementam o mesmo tipo e que possuem implementações diferentes do método gritar(). Posso fazer isso com herança ou posso fazer isso sem herança. A confusão de muitos autores de livros é que eles apresentam polimorfismo com herança, dando a impressão que tem que ter herança para ter polimorfismo. Eu prefiro apresentar polimorfismo com tipos abstratos (interface, em Java), para deixar claro que polimorfismo é 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 abstratos ou tipos concretos (herança)? Nem todo mundo concorda com a melhor forma de fazer isso. Minha opinião é:  Use tipos abstratos (interface) para fazer polimorfismo  Use herança para fatorar código comum entre várias classes Em 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