[MÚSICA] Este é o Curso de Programação Orientada a Objetos com Java. Meu nome é Eduardo Guerra. Hoje vamos valor sobre polimorfismo. Não sei se vocês já ouviram essa palavra, é uma palavra bacana. A gente vai ver que a gente já viu pouco de polimorfismo nas aulas anteriores, quando a gente falou de herança, quando a gente falou de interfaces, mas eu gostaria de falar pouco de uma forma mais específica para vocês sobre o polimorfismo si, para vocês entenderem como que ele pode ser utilizado para poder criar código mais otimizado, mais flexível. Bom, a natureza às vezes faz os animais poderem assumirem várias formas, de acordo com a necessidade estágio de vida. Por exemplo, a gente tem o caso clássico da lagarta, borboleta, onde ele começa ali sua vida como uma lagarta, aí vira casulo, onde também é uma outra forma que vai dar condições, por exemplo, de desenvolver uma nova proteção, até virar a borboleta, que também vai poder voar, e tudo mais, que condiz com a necessidade daquele estágio de vida. Então, software orientado a objeto, as classes também podem assumir a forma da superclasse, ou da suas interfaces, de acordo com a necessidade. Esse é conceito extremamente importante, no momento que eu falar assim que, olha eu tenho uma classe que ela estende uma outra classe, ela também é uma dessa outra classe, e ela pode assumir a forma dessa outra classe. Se eu falar assim, olha uma classe ela implementa uma interface? Ela é uma daquela interface! E objeto de uma classe, ele é objeto da superclasse dela, objeto de uma classe, ele é objeto da interface dela. Então, esse objeto ele pode assumir todas essas formas. Essa, digamos assim, essa mudança de forma que o objeto pode fazer, essa mudança da forma que você enxerga ele, é o que a gente chama na orientação a objeto de polimorfismo, tá? A gente falou pouco disso, quando a gente estava lá na aula de herança, eu mostrei para vocês que uma subclasse ela pode ser passada, métodos que aceitam a superclasse. A gente falou pouco disso lá, quando a gente falou de interface, eu mostrei para vocês que objeto de uma classe que implementa a interface, pode ser passado para o método, por exemplo, que aceita aquela interface e o nome disso é polimorfismo. Então é isso que é o tal polimorfismo que às vezes a gente escuta tanto na orientação a objetos. Se eu tenho uma instância ali de cavalo, eu vi lá: "Cavalo c = new Cavalo", eu posso pegar e atribuir essa variável cavalo, para uma variável do tipo animal que é a superclasse de cavalo. Da mesma forma, eu posso pegar esse objeto cavalo e atribuir para uma variável do tipo móvel, que é uma das interfaces de cavalo, e esse objeto de uma certa forma, vai assumir essa forma de móvel. Lembra que essa variável pode ser o atributo de uma classe, pode ser o parâmetro de método. Então todos esses lugares onde ele vai aceitar o móvel, vai aceitar animal, eu posso estar passando essa classe cavalo. Então como eu faria? Se eu tenho por exemplo, método classificar, que ele aceita animal, eu posso estar passando para ele cavalo ou posso estar passando pássaro ou aracnídeo, escorpião, né? Então eu posso passar qualquer objeto que, de alguma forma, é de uma classe que estende aquela classe animal, mesmo que não seja às vezes diretamente, ou eu posso ter por exemplo, sei lá, a classe bem-te-vi que estende pássaro, que estende animal, por exemplo. Da mesma forma, eu posso ir lá no método adicionar corrida que recebe móvel, eu posso adicionar cavalo, posso adicionar carro, posso estar adicionando até uma bicicleta, desde que cada desses objetos implementem aí a interface móvel. No momento que eu tenho esses métodos, eu só posso usar aqueles objetos que são definidos na classe ou na interface. Então por exemplo, o método corrida, o método corrida recebe ali cavalo, ele não pode pegar e sair usando os métodos específicos de cavalo, ele vai usar os métodos de cavalo que foram definidos no móvel. Da mesma forma ele estar recebendo ali escorpião, ali no classificar, ele não pode usar o método ferroar porque é só o escorpião que tem, ele vai usar os métodos da classe animal que é comum a todos. Se eu por exemplo, no adicionar da corrida, eu recebo móvel, e falo assim, eu vou mover esse cara até a largada. Então o que que ele vai fazer? Se eu passo para esse método cavalo, ele vai chamar o método mover da classe cavalo. Então note que o método ele está definindo a interface, mas ele está implementado na classe cavalo, então ele vai chamar a implementação do mover, da classe cavalo. Da mesma forma, se eu pegar exatamente o mesmo método e passar para ele a classe carro, ele vai chamar o método mover, não o da classe cavalo, o da classe carro. Então ele sempre vai chamar o mesmo método mover, aquele método mover que foi definido na interface, só que ele vai executar a implementação que foi definida naquela classe. Então se eu passo Cavalo ele vai mudar o mover do Cavalo, se eu passo carro, ele vai executar o mover do carro. Esse método ele é definido no contrato, ou seja, ou na interface ou na subclasse, mas a implementação é definida pela classe. Eu posso dizer que o comportamento do meu método, ele é de acordo com a classe que eu estou passando para ele, o objeto que eu estou passando para ele. Apesar de ser o mesmo método, quando eu chamar lá o mover do cavalo, esse mover vai ser diferente do mover lá do carro. Então o comportamento desse método, ele vai variar de acordo com o objeto que foi passado, e ele nem está sabendo disso, ele simplesmente está falando, amigo que eu recebi aí, move, como esse cara se move, qual o comportamento do mover, ele não sabe, está? Então eu posso inclusive ir lá, criar uma nova classe, ter uma nova implementação de mover, que quando eu passar para esse método, ele vai ser comportar dessa forma. No exemplo que a gente viu lá do comparable, se a gente pegar, por exemplo, duas classes, que às vezes podem ter as mesmas informações, mas tem implementações diferentes do comparable, ele vai ordenar de forma diferente, porquê? Porque quando ele chamar aquele método compare to, ele vai chamar dos objetos que foram passados ali. Como falei, é possível estender o comportamento de uma classe ou do método, simplesmente às vezes passando uma nova implementação daquela abstração que ele recebe. Então, se eu tenho uma classe que ela é composta por objeto que é do tipo de uma interface, e algum momento essa classe chama métodos ali, variando qual é o objeto que está ali, eu posso variar o comportamento daquela classe. Às vezes, passando objetos de classes diferentes para o mesmo método, eu posso variar o comportamento desse método. E isso é extremamente interessante e importante. A gente vai ver que, quando a gente for ver os padrões de projeto, vão ter vários que vão explorar justamente essa característica da orientação a objetos, para conseguir implementar soluções flexíveis e extremamente reutilizáveis. Então eu gosto de dizer, com certeza, que grande parte do poder da orientação a objetos, está no polimorfismo, está no facto de eu poder ter, às vezes, várias classes assumindo a forma de uma interface, ou da sua superclasse, está certo? Então, eu espero que nessa aula aqui vocês tenham entendido melhor o polimorfismo, como isso aí funciona, certo? A gente já estava dando umas pinceladas antes, aí na classe de interface, na aula de interface, na aula de herança, mas agora, a ideia era realmente fechar esse assunto para que vocês entendam como que essa característica é importante para a orientação a objetos e como que isso daí pode ser utilizado para se obter toda essa flexibilidade, toda essa, reutilização de código que se fala na orientação a objetos. É isso aí. Terminamos por aqui. Muito obrigado por assistir! [MÚSICA]