Introdução ao Polimorfismo #
O assunto em si, não é muito claro para vários programadores, e algumas pessoas explicam de forma equivocada, mais adiante vai perceber o porquê. A princípio, polimorfismo quer dizer ‘várias formas’, pode-se dizer que é o ato do mesmo código suportar diversas coisas.
O foco aqui não é a implementação e sim no conceito, por tanto irei alternar no uso da linguagem para exemplos.
1. Subtyping #
Esse é o polimorfismo que pode ser considerado entre os mais conhecidos, pois é o que muitos costumam dizer quando falam de ‘polimorfismo’. São subclasses que fornecem diferentes implementações de algum método da super classe.
public class Animal {
public void eat() {
System.out.println( "Animal eating" );
}
}
//galinha herda de Animal
public class Chicken extends Animal {
public void eat() {
System.out.println( "Chicken eating" );
}
}
//Gato herda de Animal
public class Cat extends Animal {
public void eat() {
System.out.println( "Cat eating" );
}
}
public class Test {
public void makeAnimalEat( Animal animal ) {
animal.eat();
}
public static void main( String[] args ) {
Test t = new Test();
t.makeAnimalEat(new Animal());
t.makeAnimalEat(new Chicken());
t.makeAnimalEat(new Cat());
}
}
2. Ad-hoc Polymorphism (Overloading) #
Também conhecido como sobrecarga, você basicamente terá a execução do método de acordo com quantidade ou tipos de parâmetros da função, então dependerá do que for passado. Por exemplo:
class Person
def show_data(name)
"Hey meu nome é #{name}"
end
def show_data(name,age)
"Hey meu nome é #{name} e tenho #{age} anos"
end
end
person1 = Person.new
puts person1.show_data("Victor Igor") #=> Hey meu nome é Victor Igor
puts person1.show_data("Victor Igor", 18) #=> Hey meu nome é Victor Igor e tenho 18 anos
3. Ad-hoc Polymorphism (Coercion polymorphism) #
Acontece quando um tipo primitivo ou um objeto é ‘convertido’ em outro tipo de objeto ou tipo primitivo, e essas conversões podem ser implícitas(são feitas automaticamente) ou explicitada.
Coerções são essencialmente uma forma de abreviatura que pode reduzir o tamanho do programa e legibilidade do programa, mas também pode causar erros de sistema sutis e, por vezes, perigosos. Coerções é geralmente detectada no tempo de compilação, mas em linguagens impuras como LISP, têm abundância de coerções que são apenas detectado e executado em tempo de execução.
Um exemplo de Coerção bem comum é de um número ponto flutuante que pode ser usado aonde se espera um inteiro.
float b = 2;
int a = 3.33; // implicitly coercion (coercion)
a = (int) 10.2; // explicitly coercion (casting)
4. Parametric Polymorphism #
Também é chamado de Generics em Java e C#, e templates em C++. Diferente de Ad-hoc(overloading), basicamente é uma função ou um tipo de dado que pode ser escrito genericamente para que ele possa lidar com valores de forma idêntica sem depender do seu tipo. Generics pode ser feito tanto com estruturas ou classes, por exemplo:
Estrutura:
public class GenericMethodTest
{
// método generico
public static < E > void printArray( E[] inputArray )
{
// Imprime os elementos do array
for ( E element : inputArray ){
System.out.printf( "%s ", element );
}
System.out.println();
}
public static void main( String args[] )
{
// Arrays inteiros, double e chars
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println( "Array integerArray:" );
printArray( intArray ); // passando um array de inteiros
System.out.println( "\nArray doubleArray:" );
printArray( doubleArray ); // passando um array de double
System.out.println( "\nArray characterArray:" );
printArray( charArray ); // passando um array de chars
}
}
Esse tipo de polimorfismo só ocorrem em linguagens tipadas, e não é tão comum em linguagens OO como Java e C#, e sim mais comum em linguagens funcionais como Haskell e OCaml.
5. Structural Polymorphism #
Imagine uma função que executa em uma tal estrutura de um valor. Porém ela funciona para todos os valores que são super conjuntos dessa estrutura. Calma, você vai entender. Sei que pode parecer um pouco confuso sobre essa ‘estrutura de um valor’, vamos ver um exemplo:
class Airplane{
constructor(e::<Left>, s::<Top>, d::<Right>){
this.left<- e
this.top<- s
this.right<- d
}
}
interface Direction{
left: <Left>
right: <Right>
}
move(direc: Direcao<Int, Int>){
return direc.left- direc.right
}
move(new Airplane(5, 6, 2)) ;;=> 3
move(new Direction(3, 1)) ;;=> 3
//Funcao 'mover' funciona para qualquer coisa com propriedades de direita e esquerda e não com um tipo específico.
//Mas agora imagina você misturando com Overloading e criar outra função mover, porém esperando um <Int, Float> e criar um comportamento diferente.
A maioria das linguagens tipadas por serem de tipos nominais, elas não suportam esse tipo de polimorfismo, mas você pode fazer o uso de interfaces.
6. Row Polymorphism #
Se você entender todos que já foram citados, esse você tira de letra! :) Imagine agora usar todo o poder do Structural Polymorphism com o Parametric Polymorphism! Intependente do tipo que a função mover receber, ela fará.
class Airplane{
constructor(e::<Left>, s::<Top>, d::<Right>){
this.left<- e
this.top<- s
this.right<- d
}
}
interface Direction{
left: <Left>
right: <Right>
}
mover(direc: Direction<X, Y>){
return direc.left - direc.right
}
mover(new Airplane(5, 6, 2)) ;;=> 3
mover(new Direction(3.5, 0.5)) ;;=> 3
Conclusão #
É bem importante deixar claro que o ‘tipo’ que citei, é melhor interpretá-lo como “Algo que se parece com as propriedades que sua operação está esperando”, senão estaremos excluindo a possibilidade de polimorfismo nas linguagens com tipagem dinâmica.
Os nomes dos tipos que citei também podem ter nomes diferente e são até categorizados, pode-se dizer que até um ou outro é da subcategoria de outro.
Existe muitos tipos de polimorfismo, alguns mais acadêmicos como Polytypism que já é um tipo especial de polimorfismo e que só tem em linguagens com Generalised Algebraic Datatypes (GADTs), e o F-bounded polymorphism, e nesse momento deve ter alguém inventando mais outro, então cuidado ao querer explicar polimorfismo para alguém, pois polimorfismo não tem nada a ver com OO-class-based, e sim com o conceito original de OO que é a troca de mensagens, pois é apenas a forma da mensagem ser recebida por objetos diferentes. Cabe agora você saber como a linguagem que você desenvolve implementa polimorfismo.
🙏🙏🙏
Já que você chegou até aqui, seria muito show compartilhar este artigo em sua rede social favorita 💖! Para feedback, comente ou interaja com emoji 👻
Published