Ontem na faculdade o professor estava explicando polimorfismo, ai surgiu uma duvida, e ao perguntar pra ele, ele me disse assim:
Ele perde a referencia.
Perde referencia do que?
Segue meu codigo com minha duvida.
publicclassPrincipal{publicstaticvoidmain(String[]args){Animalanimal=newCachorro();animal.comer();animal.latir();// porque eu não consigo acessar o metodo latir? }
publicclassCachorroextendsAnimal{publicvoidlatir(){System.out.println("O Cachorro esta latindo");}}
publicclassAnimal{publicvoidcomer(){System.out.println("O animal está comendo");}}
porque você executou o animal.comer() irá abrir seu metodo, dentro do metodo animal.comer() so apresenta a mensagem nada mas, assim perdeu a referencia com a classe principal
shenn
eu sei que disso, mas pq ele não permite eu executar o
animal.latir();
nel
shenn:
Ontem na faculdade o professor estava explicando polimorfismo, ai surgiu uma duvida, e ao perguntar pra ele, ele me disse assim:
Ele perde a referencia.
Perde referencia do que?
Segue meu codigo com minha duvida.
publicclassPrincipal{publicstaticvoidmain(String[]args){Animalanimal=newCachorro();animal.comer();animal.latir();// porque eu não consigo acessar o metodo latir? }
publicclassCachorroextendsAnimal{publicvoidlatir(){System.out.println("O Cachorro esta latindo");}}
publicclassAnimal{publicvoidcomer(){System.out.println("O animal está comendo");}}
Shenn, cavalo late ?
Se sim, vou ficar impressionado . O que eu quero dizer ? Todo animal (eu acho) come, mas todo animal late ? Não.
Por isso na classe Animal não contém o método latir. O método latir é especifico da classe Cachorro, entende ?
rmendes08
Isso acontece porque o Java usa o tipo da referência para saber quais métodos podem ser chamados sobre um objeto, enquanto que o tipo do objeto em si é usado para determinar qual versão do método será executado. Um acontece em tempo de compilação e o outro em tempo de execução. Isso acontece porque na prática, em tempo de compilação não é possível determinar qual é o tipo real do objeto, o compilador conhece apenas o tipo da variável de referência. Por exemplo, no método abaixo:
publicvoidfoo(Animalanimal){animal.comer();//...}
não há como saber qual é o tipo real do objeto, você sabe apenas que está recebendo um animal, se é um Gato, Cachorro, Canguru … isso não te interessa.
shenn
então é tipo assim? O meu objeto animal vai receber um cachorro..
ai o java não consegue "saber" qual tipo de animal ele esta recebendo?
por isso eu nao consigo fazer
animal.latir();
nel
shenn:
então é tipo assim? O meu objeto animal vai receber um cachorro..
ai o java não consegue "saber" qual tipo de animal ele esta recebendo?
por isso eu nao consigo fazer
animal.latir();
Como o mendes explicou, ele tem a referência a classe Animal, não a implementação dela.
Todos os métodos que não estejam na classe "Pai" não será reconhecidas por ela. Um filho sabe todos os métodos (considere tudo publico) que o seu Pai possui, por isso consegue usa-los. Todavia, o Pai só conhece seus próprios métodos, como o filho os implementou e se possui mais métodos ou não, não interessa a ele. A referência permanece sendo para a classe Pai, no seu caso, Animal.
Se quiser usar o método latir, você faz um cast direto, o que perde o sentido do polimorfismo nesse caso, ou simplesmente instancia diretamente a classe Cachorro, ai sim, ele tem a referência para o Cachorro e vai conhecer todos os seus métodos, assim como de seu Pai (Animal).
denisspitfire
ou seja…
publicclassTeste{publicstaticvoidmain(String[]args){Cachorrodog=newCachorro();dog.comer();dog.latir();}}classCachorroextendsAnimal{publicvoidlatir(){System.out.println(" O Animal esta Latindo");}}abstractclassAnimal{publicvoidcomer(){System.out.println(" O Animal esta Comendo ");}}
Podemos colocar a classe Animal como abstrata pois ela nao pode ser instanciada somente extendida… para nao dar esses problemas.
Classes mais “altas” nao sao instanciadas para ja ter uma certa segurança de qual metodo voce quer.
shenn
ahaa então seria tipo assim:
o objeto pai esta “recebendo” um objeto filho, por isso eu não consigo acessar os métodos do objeto filho…
Mas porque eu iria fazer
Animal animal = new Cachorro();
sendo que eu nao tenho como acessar os metodos da classe cachorro?
rmendes08
shenn:
ahaa então seria tipo assim:
o objeto pai esta “recebendo” um objeto filho, por isso eu não consigo acessar os métodos do objeto filho…
Mas porque eu iria fazer
Animal animal = new Cachorro();
sendo que eu nao tenho como acessar os metodos da classe cachorro?
Simplesmente porque não lhe interessa. Geralmente, quando você usa uma variável cujo tipo é uma superclasse, você não escolhe qual implementação você vai usar. Pode parecer inútil agora, mas você vai ver uma coisa chamada baixo acoplamento, que permite modularizar melhor seus programas.
[/quote]
denisspitfire
voce esta falando que esta recebendo um animal… mas animal pode ser cachorro, gato… sei la qualquer animal
voce quer comprar um animal…
dai voce espera oque quanto voce falar pro animal latir?
voce espera ele emitir um som…
porem um coelho é um animal e nao late.
oque é mais alto nivel, por questao de segurança e detalhamento voce nao pode instanciar… só extender.
shenn
ahaa deu pra entender mais ou menos… =D
porem ainda é um pouco complicado
vlw galera pelas dicaas
carloshsamaral
Amigo eu estava com a mesma dúvida e me indicaram esse link aqui.
Com ele consegui entender oque vem a ser Polimorfismo !
shenn
bom site =D
T
ThurBrum
rmendes08:
Isso acontece porque o Java usa o tipo da referência para saber quais métodos podem ser chamados sobre um objeto, enquanto que o tipo do objeto em si é usado para determinar qual versão do método será executado. Um acontece em tempo de compilação e o outro em tempo de execução. Isso acontece porque na prática, em tempo de compilação não é possível determinar qual é o tipo real do objeto, o compilador conhece apenas o tipo da variável de referência. Por exemplo, no método abaixo:
publicvoidfoo(Animalanimal){animal.comer();//...}
não há como saber qual é o tipo real do objeto, você sabe apenas que está recebendo um animal, se é um Gato, Cachorro, Canguru … isso não te interessa.
Então cara, eu saquei essa de que na compilação ele não liga pra diferença dos tipos mas na execução sim.
O unico problema restante é:
Digamos que na classe Cachorro tenho o atributo corDoPelo. E na main eu faça o seguinte:
//...Cachorroan1=newCachorro();an1.setCodDoPelo("Preta");Animalan2=an1;//Se nessa linha não da erro...an2.latir();//Por que nessa dá?
Até onde eu consegui entender de variaveis de referencia, elas não guardam o conteúdo em si, guardam apenas uma referencia para a memoria.
Aí eu fiquei na duvida… como an2 pode aceitar a mesma referencia de an1, mesmo perdendo o valor da cor?? Oq acontece?
E também, porque ele não encontra o metodo latir se ele está com a mesma referencia que an1???
(Mals por estar ressuscitando o topico dps de tanto tempo xD)
sergiotaborda
shenn:
Ontem na faculdade o professor estava explicando polimorfismo, ai surgiu uma duvida, e ao perguntar pra ele, ele me disse assim:
Ele perde a referencia.
Perde referencia do que?
Perde referencia de coisa nenhuma…
Vc definiu a veriável como sendo do tipo Animal. Objetos do tipo “Animal” não têm o método “latir” porque apenas objetos do tipo Cachorro o têm.
A variável é polimorfica no sentido que ela aceita qualquer objeto que seja um animal, mas apenas os métodos que “Animal” tem é que podem ser chamados. Como Cachorro é um Animal ele tem o método comer. Então tudo bem. Mas “Animal” não tem o método latir, logo dá erro de compilação. Simples.
Vc eve tar pensando que “mas o objeto verdadeiro é um Cachorro”. Sim, mas vc só está enxergando a parte "Animal’ dele. Se vc quiser enxergar o resto vc tem que usar a variável como sendo do tipo Cachorro ( ou usar cast, ou usar interfaces, mas isso é uma aula mais avançada).
Ou seja, a chamada é transferida ao objeto correto, mas vc pode usar as chamadas que o tipo da variável tem.
T
ThurBrum
Então… a ideia em si eu já entendi de boa… o estranho é o comportamento da linguagem em si q eu qria saber mais…
Mas já deu pra esclarecer sim!
Valeu!
sergiotaborda
As variáveis em java não contém apenas a referencia aos objetos ( veja que a referencia não é um endereço de memoria (isso seria um ponteiro) é um numero mais um numero num mapa/tabela )
Eles contém tb o tipo. Por isso se diz que java é fortemente tipado.
A variável do tipo Animal e a variável do tipo Cachoro são diferentes. Quando a referencia é a mesma, o objeto final na ponta das chamadas cai no mesmo objeto. Mas é o tipo da variável que permite ao compilador saber que método estão disponíveis para aquele tipo. Ao chamar animal.latir, a variável de animal, o compilador vê se existe esse metodo em “animal”, não existe. Logo, dá erro. É muito simples. Não têm que ver com herança. Use uma variável String e chame latir() vai dar o mesmo erro, porque string não tem o método latir. O compilador só faz esta analise simples porque ele não tem a referencia, isso só em runtime que vai existir. Então ele não tem como precorrer a referencia e ver que naquela variável existe um cachorro.
A regra é : só pode chamar método que existem no tipo da variável. Simples assim.