Discussão sobre polimorfismo

boa noite, hoje tivemos uma discussão no trabalho sobre polimorfismo, um colega meu falou que um objeto que implementa uma interface com um método por exemplo acelerar(), ele diz que este objeto é polimórfico, pois ele pode implementar uma maneira de acelerar e um outro objeto pode implementar de outra maneira. Mas eu disse que não!!!, disse que por exemplo se um Fusca implementar a interface e criar um método acelerar() e um Gol implementar o mesmo método acelerar que a interface exige, não quer dizer que é polimorfismo, pois são objetos diferentes, se o mesmo objeto Gol tivesse um outro método além do acelerar da interface, por exemplo acelerar(int velocidade) ai teria 2 métodos acelerar, dai sim seria polimorfismo, quem está com a razão, eu ou ele???

Acredito que os dois tenham razão ao defender que sua idéia seja polimorfismo.

Uma referência que cita os dois: http://pt.wikipedia.org/wiki/Polimorfismo

Você está confundindo os conceitos…

O que você falou é sobrecarga de métodos.

Polimorfismo está mais próximo do que o seu amigo falou. Nesse caso dos carros por exemplo significa que se tanto a classe Gol quanto a classe Fusca implementam a interface Car. Ambas podem ser chamadas a partir de uma referência Car, devido ao fato de obrigatoriamente as classes que implementam a interface terem que implementar os métodos definidos na mesma. Por exemplo:

[code]// Eu posso criar uma instância de objeto Gol e atribuí-la a uma variável de referência car
Car car = new Gol(); // aqui eu poderia passar tanto uma instancia de Gol quanto de car já que as duas implementam a interface CAr

// Também poderia fazer assim
Car car = new Fusca();

// A vantagem disso é que, independente de ser Fusca ou Gol, eu sei que posso chamar o método acelerar já que ele está definido na interface
car.acelerar();[/code]

Dessa forma, o comportamento será diferente a depender de qual classe está sendo usada. A essa possiblidade é que chamamos de polimorfismo. Tenho comportamentos diferentes para instancia do mesmo tipo. Ou seja, no final das contas, sendo Fusca ou Gol, a instância é de Car.

Daí eu tenho que o comportamento acelerar de Car pode ser diferente a depender da classe concreta com a qual se está trabalhando.

Não sou muito bom com as palavras, mas espero que tenho ajudado…

Concordo com o AbelBueno, pois o polimorfismo pelo que estudei e entendi vêm da capacidade em sobreescrever um método (mudando apenas seu conteúdo), quanto da capacidade de mudar sua assinatura.

Só completando… segundo Kathy Sierra, qualquer objeto que passe no teste É-UM pode ser considerado polimorficos…

Você pode chamar ele de formas diferentes… tanto como Car() ou como Fusca() por exemplo… e tbm tem o lance dos métodos que eu tinha falado…

Com relação a sobrecarga, ainda não tinha escutado falar que sobrecarga fosse polimorfismo… e não confio muito na Wikipedia… então vou dar uma pesquisada melhor…

Isso é sobrecarga de métodos e não polimorfismo…

Nada melhor que a própria Oracle para explicar… tá ae mais ou menos o que eu falei… direto na documentação Oficial…

http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html

nandooliveira esta correto.

Outra fonte de informação muito boa e simples é a própria apostila FJ-11 da Caelum, cujo qual esta disponivel para download.

Agora um detalhe, se sua interface exige um atributo X, então todos vão ter que declara-lo para seu funcionamento.

E mesmo se não houvesse necessidade, um tratamento poderia ser feito dentro da interface…

bom, a parte do polimorfismo por sobrecarga de métodos e da sobrescrita por herança eu intendi, mas a da interface não me caiu bem ainda, imaginemos o seguinte código abaixo, aonde está o polimorfismo nele??? no caso só existiria polimorfismo se existisse outra classe que implementasse MeioTransporte?? pois da forma que está abaixo tenho somente uma forma de comportamento do método!!!

[code]public class Carro implements MeioTransporte {
@Override
public void andar() {

}

}

interface MeioTransporte{
void andar();
}[/code]

acredito que no caso abaixo, teria polimorfismo apenas em Fusca!

[code]class Fusca extends Carro{
public void andar(){

}

}

public class Carro implements MeioTransporte {
@Override
public void andar() {

}

}

interface MeioTransporte{
void andar();
}[/code]

"O polimorfismo, em particular, permite escrever programas que processam objetos que compartilham a mesma superclasse (direta ou indiretamente) como se todos fossem objetos da superclasse…Contar com o fato de que cada objeto sabe “fazer a coisa certa” ( isto é, faz o que é apropriado a esse tipo de objeto) em resposta à mesma chamada de método é o conceito-chave de polimorfismo."

Retirado do livro dos Deitel

Há muitas referências na internet sobre isso, inclusive um post aqui no guj mesmo:

Muita gente considera sobrecarga como um tipo de polimorfismo, o ad-hoc (conforme citado na wikipedia)
Pesquisar no google por ad hoc polymorphism trará inúmeras referências.

Por fim, não dá pra se basear no que a documentação da Oracle (ou Sun) fala como verdade absoluta.

O que no Java chamamos de Generics é conhecido como polimorfismo paramétrico em linguagens funcionais
(Muita literatura formal cita isso: Real_World_Haskell e Haskell The Craft Of Functional Programming, por exemplo)

Interessante a sua pergunta. Eu também sempre fico em dúvida quanto à esse conceito. Vou seguir o tópico e esperar que alguém do fórum responda :slight_smile:

Um Abraço,

Amigos, pesquisando na “internet” pelo termo polimorfismo em português encontrei algumas páginas de professores de faculdade e esta me pareceu relevante:
http://walfredo.dsc.ufcg.edu.br/cursos/2003/progII20031/aulas/o_que_e_polimorfismo.htm
Nela, o professor define o termo polimorfismo fora do ambiente programático para depois aplicar sobre os conceitos de orientação a objeto.
Indo por este lado, a sobreescrita de metodos é uma maneira de gerar varías formas do tipo.
Entendo então que a interface define um tipo e cada uma de suas implementações é uma (poli)forma daquele tipo.
Outro conceito é a sobrecarga de metodos (em detrimento sobreescrita de metodos) eu entendo que se uma forma define um metodo diferente da interface, este metodo não faz parte do tipo da interface, nem dá chamar através da interface, logo não é uma (poli)forma do tipo da interface.

Por outro lado, não creio que o site da Oracle/Sun possa ser nosso “oráculo” nos conceitos sobre orientação a objetos pois java é apenas uma das linguagens atuais orientada a objetos.

Existem diferentes tipos de polimorfismo.

O primeiro é o polimorfismo dinâmico, que ocorre em Runtime. Esse é o que seu amigo citou. O mesmo método, agirá de maneiras diferentes, de acordo com o objeto que a interface referencia. Exemplo:

Carro c = new Fusca(); c.acelerar(); //Acelera como um fusta c = new Gol(); c.acelerar(); //Acelera como um gol.

O segundo tipo, é o polimorfismo estático. É chamado assim pois o comportamento polimórfico é criado pelo compilador.
Nessa categoria, encaixa-se a sobrecarga de métodos (que você citou) e o polimorfismo através de templates.
Um exemplo de sobrecarga:

[code]public void acelerar(int xyz) {
System.out.println("Aceleração inteira: " + xyz);
}

public void acelerar(double xyz) {
System.out.printf(“Aceleração double: %.2f%n”, xyz);
}

acelerar(10); //Chama o método 1
acelerar(10.0); //Chama o método 2[/code]

Muitos autores de linguagens sem outras formas de polimorfismo estático não se referem ao polimorfismo estático como polimorfismo, daí a discussão com seu colega. Isso porque, o polimorfismo na sobrecarga geralmente muda o comportamento do método, de modo a ajusta-lo para ter um comportamento consistente com o parâmetro de entrada, mas geralmente com a mesma intenção do método original. É muito raro fazer uma sobrecarga, sem que se inclua parâmetros, que mude completamente o comportamento do método.

Finalmente, há o polimorfismo estático paramétrico (com templates e macros). Ele existe em linguagens como o C++ e linguagens funcionais.
Lá você poderia criar uma classe genérica para representar uma lista de objetos:

template <typename T> class Vector { private: T[] objects; int size; int count; public: void add(T* t); void get(int index); void remove(int index); };

Entretanto, por que desperdiçar um boolean em cada índice do array (o que faz usar 1 byte por boolean), se podemos representar 8 booleans num único byte? Nesse caso, poderiamos criar uma classe especializada, para quando o tipo fosse boolean:

template <> class Vector<bool> { private: unsigned char[] objects; int size; int count; public: void add(T* t); void get(int index); void remove(int index); };

No uso:

vector<int> xyz; //Cria um vector para inteiros com a implementação normal vector<bool> abc; //Cria um vector para booleans com a implementação otimizada