Dúvida sobre polimorfismo[Resolvido]

17 respostas
T

Aê galera, beleza!

É o seguinte.
Não é bem uma dúvida, é que eu lí uma apostila da internet, a parte de polimorfismo, e tentei implementar no código o que eu entendi do assunto. Segue o código abaixo.

abstract class Ave 
{
	private String nome;

	public Ave(String nome){
		this.setNome(nome);
	}

	public void voar(){
		System.out.println("Ave voando!!!!!!!!!!");
	}

	public void setNome(String Nome){
		this.nome = nome;
	}

	public String getNome(){
		return this.nome;
	}
}
class Passaro extends Ave
{
	public Passaro(){
		this("Passaro qualquer");
	}
	
	public Passaro(String nome){
		super(nome);
	}

	public void voar(){
		System.out.println(super.getNome() + " voando!!!!!!!!!!");
	}
}
class Galinha extends Ave 
{
	public Galinha(){
		this("Galinha qualquer");
	}

	public Galinha(String nome){
		super(nome);
	}

	public void voar(){
		System.out.println("A galinha " + super.getNome() + " nao sabe voar!!!!!!!");
	}
}
class MandarVoar 
{
	public void voar(Ave a){
		a.voar();
	}
}
class TestePolimorfismo 
{
	public static void main(String[] args) 
	{
		Ave ave = new Passaro("Churel");
				
		MandarVoar m = new MandarVoar();		
		m.voar(ave);

		try
		{
			System.in.read();
		}
		catch(java.io.IOException e)
		{
			e.printStackTrace();
		}
		
		ave = new Galinha("Furusteca");
		m.voar(ave);
	}
}

O programa tá imprimindo:

null voando!!!!!!!!

A galinha null nao sabe voar!!!!!!!!!

Ou seja, não está imprimindo o nome das aves passadas nos construtores.

Algém sabe onde está o erro? Já fiz de tudo mas não consegui encontrar.

Outra coisa, se alguém souber alguns links bons falando sobre polimorfismo, posta aí também. Se não for pedir de mais, é claro.

Valeu!!!!!!!!

17 Respostas

LPJava

assim, uma coisa que nao achei logico, vc tem uma class abstrata com metodos concretos, nao quer dizer que errado, porem nao é valido, quando se cria uma class abstrata é interessante que os metodos tb sejam abstratos para que se seja implementado por uma class concreta. Para entender a essencia de polimorfismo, cara é bom vc pegar exercicios simples e praticar muito, mais muito mesmo, olha um exemplo legal que vou ti dar:

class Carro{
public void setMarca(){System.out.println("marca super");}
}
class Bmw extends Carro{
public void setAno(){System.out.println("ano sub");}
}
class Teste{
public static void main(String args[]){
Carro c = new Bmw();
c.setMarca();
c.setAno(); // isso roda?
}
}
/* uma dica minha mastige, bastante a parte inicial de polimorfismo, mesclando com classes, implementações de interfaces quando vc sacar bastante disso cara, ai vc deve se concentrar em chamada de construtores no uso da herança e depois no uso dos blocos try{} e catch*/

agora esse codigo compila? senao compila diz ai pq nao compila…hehe não to querendo testar vc… mais isso ai é o basico de uma sintaxe sobre polimorfismo…
vlw… espero ter ajudado… a teoria de polimorfismo eh show de bola… mais tome bastante cuidado e atenção algumas regras que devem ser lembradas sempre… :stuck_out_tongue:

T

Caro camilolopes.
Se você está querendo me testar, você me pegou. :frowning:
Realmente não compila. E eu não consegui entender o porquê.
Preciso estudar mais essa parte.

Pelo que eu entendi, o polimorfismo consiste em uma idéia que em uma ierarquia de classes, onde subclasses de uma mesma superclasse têm métodos comuns mas implementações diferentes, a JVM sabe distinguir qual o método correto, da classe correta, chamar, através da superclasse.

No seu exemplo: A classe Carro é uma generalização de um carro, ou seja, todo carro tem pneu, volante etc (apesar de você não ter colocado no código, mas acho que a idéia é essa). Então, através da OO, pode-se implementar uma classe geral, onde outras classes mais específicas, no caso Bmw, herda as implementações normais para qualquer carro, e complementa-se com implementações (os métodos) específicos. Mas aí é onde entra o polimorfismo, eu acho. Se o Bmw é um carro, então pode-se declarar um carro e instanciar um Bmw (Carro c = new Bmw();), ou pode-se instanciar um Fuscar com a mesma variável c, pois fuscar também é um carro.
Agora se foi instanciado um Bmw, por que o método dessa classe não é reconhecido?

Não sei se fui claro na minha definição. A verdade é que preciso estudar mais essa parte.

Enfim, tenho conciência de que não entendi a idéia do polimorfismo direito, então vou pesquisar mais.

Mas dá uma olhada nas minhas classes postadas, tenta entender o que eu quis sugerir com as classes e com o método voar() da classe MandarVoar.

Enquanto a saída do programa, não tô conseguindo entender o null. Acho que essa questão não tem nada a ver com o polimorfismo.

Aguém pode explicar o null!!!

K

Tiago,

mto mto simples

Seu unico problema foi de sintaxe....porque o polimorfismo foi utilizado correto.

Altera a classe Ave no metódo setNome e passa o parametro com letra minuscula (uma vez que vc declarou ele com letra minuscula - padrao de atributo).

faça assim:
public void setNome(String nome){
 		this.nome = nome;

Só isso.....agora pode rodar que vai dar certo

:lol:

Mantu

Só pra acrescentar uma coisinha:
Nos métodos voar das classes Galinha e Passaro, não é necessário você utilizar a palavra chave super para invocar o método getNome, pois a relação de herança faz com que este método se propague da classe pai para as classes filhas. Aliás, eu acho pouco recomendado você utilizar o super, pois se você tiver uma classe que sobrescreva o getNome, e invocar super.getNome, você pode estar quebrando o polimorfismo de forma não intencional…

T

Tiago,

mto mto simples

Seu unico problema foi de sintaxe…porque o polimorfismo foi utilizado correto.

Altera a classe Ave no metódo setNome e passa o parametro com letra minuscula (uma vez que vc declarou ele com letra minuscula - padrao de atributo).

faça assim:
Code:

public void setNome(String nome){
	this.nome = nome;

Só isso…agora pode rodar que vai dar certo

Cara^@$2¨&lº§!%*h&§§#o
Era só isso mesmo.
Passei a tarde toda ontem quebrando a cabeça nisso.

Desculpem se fiz vocês perderem tempo com isso.
Mas de qualquer forma, obrigado.

LPJava

a respeito de minha class coloquei ume pegadinha mesmo, para vc ver que polimorfismo e sua essencia… e oque vc pode deparar… nao quis testar vc nao… quem sou eu… apenas mostrar… o seguinte a questao do meu exemplo é que criei isso:

Carro c = new Bmw();

minha variavel c é do tipo Carro blz? e referencia a Bmw certo? isso aqui ta certo pq bmw é um Carro… mais o erro está quando faço isso c.setAno(); se vc me disse ai que Bmw faz tudo que Carro faz, mais carro nao tem ano… entao isso nao compila…compilava se carro tivesse setAno(); ou ver alterasse assim:

Bmw b = new Bmw();
b.setAno();

isso funciona… sao algumas regrinhas a seguir e ter atenção… no caso do seu exemplo a galera ai ja respondeu… :smiley:
vlw!! mais polimorfismo eh um dos assunto que mais gostei de estudar alias gosto… hehe

K

ahhhhh

fazendo uma correção no comentário do camillo:

Camillo, não necessariamente vc precisa ter todos metodos abstratos numa classe abstrata. Voce deve ter pelo menos um método…(mas não todos). Sendo essa uma das diferenças entre classe abstrata e interfaces.

Então se eu quiser ter um método concreto numa classe abstrata, eu posso ter…desde q exista um método abstrato declarado nela.

Mantu

A sua correção dá a entender que uma classe para ser abstrata deve ter pelo menos um método abstrato. Dá a entender também para ser abstrata também não pode ter apenas métodos abstratos.
Bom, isso não é verdade…
Para uma classe ser abstrata, ela precisa apenas ser declarada como tal. Veja o exemplo a seguir:

abstract class AAA{
	public String blablabla() {
		return "blablabla";
	}
}

É uma classe abstrata que não tem nenhum método abstrato.
E essa aqui agora:

abstract class BBB{ public abstract String bibibi(); }
É uma classe abstrata que tem apenas métodos abstratos.
Ambos exemplos compilam normalmente.
O que não pode de verdade, é ter uma classe não-abstrata que tenha um ou mais métodos abstratos. Isso sim não pode:

class CCC{
	public abstract String momomo();
}

Isso aí, não compila nem com reza braba…
Resumindo: Uma classe abstrata, não precisa ter método(s) abstratos, mas uma classe com um ou mais métodos abstratos, deve ser abstrata.

K

Eh Mantu…

talvez eu tenha errado na forma de expressar, mas o que eu quis dizer era bem por ai. O que eu quis corrigir, foi quando o camillo disse que não é valido uma classe abstrata ter métodos concretos.

LPJava

karen, se vc olha entre linhas observe o que falei que nao é LOGICO eu criar uma classes abstrata e implementar todos os metodos dela na propria class… mais que isso nao eh errado pode fazer sim… mais se eu crio uma class abstract o mais logico… e perto da teoria seria de ter metodos abstratos a qual uma classe concreta implementa esses metodos como quiser… leia novamente e veja minhas entrelinhas nao falei momento nenhum que estava errado… :stuck_out_tongue:

K

Verdade, agora consegui entender o que vc quis dizer.

Uai…pelo menos vai nossa conversa vai servir pro pessoal que tem duvida sobre isso :lol:

Eu tinha interpretado de outra forma sua colocação…mas pela sua explicação agora…eu consegui entender seu comentario.

Bom…axo q pra isso serve o forum ne? discussões :smiley:

T

Só pra acrescentar uma coisinha:
Nos métodos voar das classes Galinha e Passaro, não é necessário você utilizar a palavra chave super para invocar o método getNome, pois a relação de herança faz com que este método se propague da classe pai para as classes filhas. Aliás, eu acho pouco recomendado você utilizar o super, pois se você tiver uma classe que sobrescreva o getNome, e invocar super.getNome, você pode estar quebrando o polimorfismo de forma não intencional…

Mantu,
já sabia que não era necessário o super, como você falou. Eu aprendi na faculdade que o super deve ser usado para chamar um método herdado, pois facilita a leitura do código, já que sabemos que o método chamado pertence a classe pai ( ou ao avô, sei lá) ao vermos o super, e também evita a recursividade, caso desejarmos chamar dentro de um método sobrescrito o método da superclasse.

Agora, eu não entendi como o uso super pode quebrar o polimorfismo. Se não for pedir demais (o guj deixa a gente meio folgado), explica isso aí velho.

Obrigado a todos que postaram!!!

T

Camilo,
não sei também se estou entendendo mau o que você tá querendo dizer, mas eu acho que você está se referindo a interfaces, ao dizer que não é lógico implementar todos métodos concretos em classes abstratas. Uma classe abstrata serve apenas como base para compôr outras classes através da herança, logo ela não pode ser instanciada. Então se eu quero implementar métodos abstratos em outra classe, acho melhor o uso de uma interface. Ou não?

Na classe Ave, eu declarei como abstract por que não achei necessário instanciar a classe, apenas herdar seus métodos.

Portanto, eu acho lógico sim implementar métodos concretos dentro de classes abstratas. Mas cada um tem sua forma de enxergar as coisas.

Se eu estiver lhe entendido mau, desculpe.

Mantu

Discordo. Eu vejo uma classe abstrata como a representação de algum conceito abstrato, do qual não faz sentido se ter um objeto. Mas nada impede que uma classe assim possa definir comportamentos (métodos) padrão para as suas classes filhas. Isso pode acontecer em uma relação de classes em que na classe pai, os métodos implementados trazem instruções que todas as classes filhas poderiam executar. E as classes filhas então, poderiam realizar nesses métodos algumas instruções específicas, típicas de si, e em algum momento invocar ou não o comportamento padrão disponibilizado pela classe pai.

Mantu

Acho que usei um termo inapropriado, mas o que eu quis dizer com quebrar o polimorfismo seria fazer algo assim: Eu não consigo pensar em um exemplo que ajude, mas pode acontecer de uma classe filha sobrescrever um método da classe pai, e um outro método da classe filha precisar invocar o método sobrescrito. Algo assim:

abstract class Pai{
	protected String nome;
	
	public void a() {
		System.out.print("Pai");
	}
	
	public abstract void b();
}

class Filha01 extends Pai{
	public Filha01(String nome) {
		this.nome = nome;
	}

	public void a() {
		System.out.print("Filha01");
	}
	
	public void b() {
		System.out.print(nome + " diz: ");
		System.out.print("Eu sou a classe ");
		a();
		System.out.print(". Não apito nada por aqui...");
	}
}

class Filha02 extends Pai{
	public Filha02(String nome) {
		this.nome = nome;
	}

	public void a() {
		System.out.print("Filha02");
	}
	
	public void b() {
		System.out.print(nome + " diz: ");
		System.out.print("Eu sou a classe ");
		super.a();
		System.out.print(". Eu fico quietinha na minha...");
	}
}

class Teste{
	public static void main(String[] args) {
		Pai
			p1 = new Filha01("Gertrudes"),
			p2 = new Filha02("Marilu")
		;
		
		p1.b();
		System.out.println();
		p2.b();
	}
	
}

A classe Filha02 seria o caso da pessoa que utiliza o super só com o intuito de tornar o código mais legível, só pra ficar explicito que a superclasse de Filha02 tem um método chamado a. Só que nesse caso, o método a ser executado não vai ser o a da classe Filha02, e sim o da classe Pai… Daí o resultado é isso aqui:

Gertrudes diz: Eu sou a classe Filha01. Não apito nada por aqui...
Marilu diz: Eu sou a classe Pai. Eu fico quietinha na minha...

Acho que não, Marilu… :lol:

LPJava

Assim mantu nao disse q era errado nem certo - meio termo, mais se eu crio uma classe abstrata vou deixar que a classe filha implemente meus metodos e nao que eu implemente os metodos ja que sou abstrata, pode posso… implementar alguns metodos mais se eu tenho 3 metodos em uma class abstrata e implemento todos nela eh melhor declarar ela como concreta e uma subclass vai herda sempre e ai eu faço um subcricacao desse metodo… que que qdo um metodo eh herdado por uma subclase ele nao vai ser herdado por outra subclass da subclasse que herdou da super…

Mantu

Só que se você fizer a classe pai concreta, você permite que sejam criadas instâncias da classe Pai, o que as vezes você pode quere barrar.

Criado 30 de janeiro de 2007
Ultima resposta 30 de jan. de 2007
Respostas 17
Participantes 4