Polimorfismo... ora entendo, ora não!

Pessoal me explica pq eu iria fazer isso:

class A {} class B extends A{}

A meuA = new B();

certo… agora o objeto A é uma instancia de B e tem acesso aos métodos q tenho em B, mas não era mais facil criar um B logo??

B b = new B();

Qual é o benefício disso??

List x = new ArrayList();

pq nao usar:

ArrayList x = new ArrayList();

???

Map a = new HashMap();

HashMap a = new HashMap();

Se o motivo é ter acesso aos métodos da classe da direita, pq nao criar uma logo… to confuso com isso =\ :?

Se amanhã você criar uma classe C filha de A, o teu sistema vai continuar funcionando trabalhando com objetos A, B e C :wink:

Por exemplo Animal, Animal tem um método comer(), então Gato, Cachorro e Galinha são animais e herdam comer (que podem ser sobreescritos)…

Se você tiver um método em teu sistema para alimentar os animais, você vai criar uma referência para a classe Animal() e nela irá adicionar os animais Gato(). Cachorro() e Galinha(), onde cada animal vai Comer() do “modo” sobreescrito ou no “modo” default Animal…

Deu para sacar? Tu trabalha de uma forma mais genérica e desta forma tu não precisa criar vários métodos (gatoComer(); cachorroComer(); galinhaComer()) no teu sitema sabendo que Animal().comer() já resolve o teu problema…

completando…

Se você tiver um método que recebe como parâmetro List<Animal>, nesta lista você poderá ter tanto objetos Gato, Cachorro como Galinha…
Para alimentar esses animais específicos (por exemplo Cachorro come Carne, Gato come peixe e Galinha come milho), quem vai saber isso eh o Objeto Filho através da sobreescrita, em tempo de execução (conforme o tipo do objeto)…

Desta forma tu pode ter 1 método para alimentar Qualquer Animal, e não precisa implementar 1 método por Animal

vc não entendeu minha pergunta… eu não questionei isso que vc explicou, eu só quero saber pq disso:

classe pai x = new classe filha()

se a classe filha tende a ser mais especializada q a classe pai, pq colocar uma referencia filha numa instancia pai??

classe filha x = new classe filha() -> isso eu entendo…

classe pai y = new classe filha() -> isso eu nao entendo.

Ao contrário… a classe pai é mais genérica… a classe filha é uma especialização.

Animal é classe pai… só contém o que todos animais contém, porém, cachorro é classe filha e contém especificações de cachorro que o diferem de outros animais, assim como as outras classes filhas de animal contem informações específicas de cada animal.

ops escrevi errado, eu quis dizer mais especializada.

mas vcs não tao entendendo… eu nao to questionando isso q vcs tao falando!

eu sei q a cada especialização entram novos metodos etc e tal.

SE A CLASSE FILHA É MAIS ESPECIALIZADA Q A CLASSE PAI, porque dessa linha:

PAI p = new FILHO();

Vou dar um exemplo mais pratico pra complementar o que o eltonk falou.

Imagine que a sua aplicação usa um Map, e tem vários métodos que recebem esse Map como parametro, e você decidiu usar a implementação Hashtable, aí ficaria assim:

[code]public void metodo1(Hashtable ht){
//implementação
}

public void metodo2(Hashtable ht){
//implementação
}

public void metodo3(Hashtable ht){
//implementação
}[/code]

E você faz isso:

[code]Hashtable ht = new Hashtable();

metodo1(ht);[/code]

Isso funciona perfeitamente.

Um dia você descobre que a performance de HashMap é melhor que Hashtable porque ele não é sincronizado e você não precisa de sincronismo, então você decide mudar:

Pronto, agora seus 3 metodos pararam de funcionar! :shock:

Porem se você tivesse feito assim:

public void metodo1(Map map){ //implementação } public void metodo2(Map map){ //implementação } public void metodo3(Map map){ //implementação }

E chamado assim:

Map map = new Hashtable(); metodo1(map);

Agora você poderia simplesmente mudar o new Hashtable() para new HashMap() que não afetaria em nada o restante do código.

Outro caso seria você ter um metodo que pode processar um List, se você implementar esse metodo recebendo diretamente um ArrayList, você estará obrigando quem usa esse metodo a te passar um ArrayList, se você precisar usar exatamente o mesmo codigo para processar um LinkedList por exemplo, você terá que fazer outro metodo, porque o que você tinha feito processa ArrayList, não LinkedList, sendo que as duas são List.

Por isso, procure sempre trabalhar com os tipos mais genéricos, para você ter flexibilidade de mudança e reutilização de código.

Ok?!!

Cara… eu entendi a sua pergunta e espero não responder besteira… se falar coisa errada espero que me corrijam.

Pelo que eu sei, você declara um Animal a = new Cachorro(); se vc quiser que o cachorro seja tratado como animal.

Suponhamos que o cachorro tem o metodo public void levantaAPataNoPoste()

Se vc declarar cachorro a = new cachorro(), o metodo levantaAPataNoPoste poderá ser chamado por esse objeto.

Se vc declarar animal a = new cachorro(), vc saberá que a é um cachorro, mas está sendo tratado como animal e não poderá chamar o método levantaAPataNoPoste().

MAP a= new HASHMAP();

a é um objeto da interface MAP com caracteristicas da classe HASHMAP.

HASHMAP a= new HASHMAP();

é um simples objeto da classe HASHMAP.

Polimorfismo: -http://www.dca.fee.unicamp.br/cursos/PooJava/polimorf/index.html"…Polimorfismo é o princípio pelo qual duas ou mais classes derivadas de uma mesma superclasse podem invocar métodos que têm a mesma identificação (assinatura) mas comportamentos distintos, especializados para cada classe derivada, usando para tanto uma referência a um objeto do tipo da superclasse. A decisão sobre qual o método que deve ser selecionado, de acordo com o tipo da classe derivada, é tomada em tempo de execução, através do mecanismo de ligação tardia…"

Acho que ele sabe o que é polimorfismo Pedro, o que ele está questionando é o motivo pra usar.

vou explicar como isso funciona, uma exemplo que me fez intender bem o polimorfismo

vamos supor que vc tenha diversas classes filhas de A,

e vc tem uma classe que por ventura que pode retornar diversos objetos, relacionados ao A.

como vc faria isso funciona se nao usasse o nome da classe mae, nao funcionaria.

vo explicar com codigo pq estou me perdendo dhuashduas

essas sao minhas classes

[code]Class Mamifero {

abstract public Object nome();

}

class cachorro extend mamifero{

public Object nome(){
//implementacao
return object
}

}

class gato extend mamifero{

public Object nome(){
//implementacao
return object
}

}[/code]

agora vai aonde eu vo tirar proveito do polimorfismo

e agora vc vai fazer oq no metodo main

[code]class queroqualqueranimal {

public static void main teste(String[] args){

    cachorro Cao = new Cachorro()

    Object p = cao.getNome();

}
}[/code]

vc pode fazer issoo, EH CLARO QUE NAO, vc nao sabe que tipo de objeto vem ali.

dai vc pensa blz entao eu uso um casting (cachorro). “object p = (cachorro) cao.getNome()”

ahhh eh espertaoo vc fez um casting pra cachorro, mais e se vier o gato que que ti faz em em???

[color=red][size=18]aiii entra o polimorfismo [/size][/color]

[code]class queroqualqueranimal {

public static void main teste(String[] args){

    mamifero Cao = new Cachorro()

    Object p = (mamifero) cao.getNome();

}
}[/code]

agora eu sei que vai vir um objeto do tipo mamiferoo, pode vir cao, gato, baleia tudo que vc possa imaginar, isso poco importa para min e para o codigo ele sabe que eh do tipo mamifer.

cara eu sei que nao fui muito claroo nas explicaçoes mais espero que tenha intendido, eh que escrevi meio que na preça hdasuhduas

falow abs

[quote=paulohrl]Cara… eu entendi a sua pergunta e espero não responder besteira… se falar coisa errada espero que me corrijam.

Pelo que eu sei, você declara um Animal a = new Cachorro(); se vc quiser que o cachorro seja tratado como animal.

Suponhamos que o cachorro tem o metodo public void levantaAPataNoPoste()

Se vc declarar cachorro a = new cachorro(), o metodo levantaAPataNoPoste poderá ser chamado por esse objeto.

Se vc declarar animal a = new cachorro(), vc saberá que a é um cachorro, mas está sendo tratado como animal e não poderá chamar o método levantaAPataNoPoste().[/quote]

Taaa! mas é isso q eu quero saber!! pra que eu vou querer q meu cachorro seja tratado como animal??

se eu especializei para classe cachorro que já herda de animal… eu posso usar os métodos de animal na classe cachorro…! Pra que eu vou ter o trabalho de especializar… criar novos métodos para a classe cachorro se depois vou trata-la como animal??

mew eu devo ser mto lerdo mesmo… rsrsr mas é isso q nao to entendendo!!

[quote=jairelton]

Por isso, procure sempre trabalhar com os tipos mais genéricos, para você ter flexibilidade de mudança e reutilização de código.

Ok?!![/quote]

Acho q entendi isso… tipo, então sempre é melhor eu usar a classe mais genérica?

Tipo se eu tivesse

A
B herda A
C herda A
D herda A

nas minhas implementações eu devo sempre instanciar:

A x = new A();
A x = new B();
A x = new C();
A x = new D();

ao invés de:

A x = new A();
B x = new B();
C x = new C();
D x = new D();

Acho que saquei a jogada dos métodos…!

cara pense assim, vamos supor que qualquer dia vc queira criar uma classe que imprima a sua lista de animais.

vc vai criar uma classe com 300 IF ???
se for cachorro
faça isso
se for pato
faça isso
ser for papagaio
faça isso.

pq vc nao faz uma classe que recebe um Animal qualquer nao importa se eh cao gato, papagaio, piriquito.

e la dentro nada de ifs. vc usa um casting(Animal) e jah eras vc faz em uma unica linha, o que faria com 300 ifs.

presta atençao no mundo de codigos que vc economizou

obs: o ideal eh usar interfaces, herança quebra encapsulamento, pelo fato de vc ter que conhecer a classe super para poder usa-la no classe filha.

iwallas, somente para finalizar com “chave de ouro”, se tiver tempo e dinheiro eu recomendo a leitura deste livro

Padrões de Projeto (Design Patterns)
http://www.temporeal.com.br/produtos.php?id=170002

Uma leitura agradável e suave (bom, em partes …) que explica legal estes tipos de conceitos da OO, e junto alguns principais design patterns.

Roger Leite

[quote=iwallas][quote=paulohrl]Cara… eu entendi a sua pergunta e espero não responder besteira… se falar coisa errada espero que me corrijam.

Pelo que eu sei, você declara um Animal a = new Cachorro(); se vc quiser que o cachorro seja tratado como animal.

Suponhamos que o cachorro tem o metodo public void levantaAPataNoPoste()

Se vc declarar cachorro a = new cachorro(), o metodo levantaAPataNoPoste poderá ser chamado por esse objeto.

Se vc declarar animal a = new cachorro(), vc saberá que a é um cachorro, mas está sendo tratado como animal e não poderá chamar o método levantaAPataNoPoste().[/quote]

Taaa! mas é isso q eu quero saber!! pra que eu vou querer q meu cachorro seja tratado como animal??

se eu especializei para classe cachorro que já herda de animal… eu posso usar os métodos de animal na classe cachorro…! Pra que eu vou ter o trabalho de especializar… criar novos métodos para a classe cachorro se depois vou trata-la como animal??

mew eu devo ser mto lerdo mesmo… rsrsr mas é isso q nao to entendendo!![/quote]

Porque um dia você pode enjoar de ter um cachorro e pode decidir trocar para um gato, e se voce fizer uso das suas classes especializadas em outras partes do código vai ter que reimplementar tudo…

Quando voce diz que é um animal, voce está deixando suas classes mais flexiveis, afinal um animal pode ser um cachorro, um elefante ou um jacare, coisa que não acontece quando se usa uma classes especializada, afinal um cachorro não é um elefante certo?

A graça é você programar para especificações, não para implementações. Por exemplo, se você precisa montar uma coleção de objetos e passá-la para outros métodos e outras classes (que não necessariamente foram ou serão feitos por você) adicionarem itens, removerem itens e iterarem sobre ela, você poderia fazer algo assim:

Collection<String> minhaLista = new ArrayList<String>(); objetoDaClasseA.trataLista(minhaLista); objetoDaClasseB.trataLista(minhaLista); //...

Um dia, você pode precisar que os dados da sua lista fiquem ordenados e não se repitam. Neste caso, o ArrayList não seria a classe correta a ser usada, mas você pode trocar a sua lista para ser um HashSet em apenas um local do código, sem afetar a ClasseA ou a ClasseB, que esperam por uma Collection.

Aaaaaaaaaah!! tá! agora entendi! vlew pessoal! :wink: