Dúvida Métodos Abstratos [RESOLVIDO]

Bom dia ^^

Estou com dúvidas em um programa de gerenciamento dos correios que estou fazendo.

O programa possui uma classe abstrata chamada Correspondência.

O programa deve enviar Telegramas, Cartas, Sedex e Sedex10, listá-los e calcular o faturamento de todos individualmente. Cada uma dessas opções são classes que herdam a classe Correspondência.

Minha dúvida está em listar e calcular o faturamento, meu professor pediu para criar um vetor correspondencia e armazenar todas as informações nele (até aí beleza), mas depois pediu para listar separadamente, como irei saber qual parte do vetor é telegrama ou carta… se todas as informações estão num mesmo vetor? :s

Vou postar o código da classe correios para ilustrar melhor ^^

package trab;

import java.util.Scanner;

public class Correios {

	private static final int MAX_CORRESPONDENCIAS = 30;
	private int numCorrespondencias;
	private Correspondencia correspondencias[];
	

	public Correios(int MAX_CORRESPONDENCIAS) {
		correspondencias = new Correspondencia[MAX_CORRESPONDENCIAS];
		
	}

	public Enderecavel dados_Enderecavel(String end) {
		Enderecavel e = new Enderecavel();
		Scanner in = new Scanner(System.in);
		System.out.println("Nome do " + end + ": ");
		e.setNome(in.nextLine());
		System.out.println("Logradouro do " + end + ": ");
		e.setLogradouro(in.nextLine());
		System.out.println("Cidade do  " + end + ": ");
		e.setCidade(in.nextLine());
		System.out.println("UF do " + end + ": ");
		e.setUf(in.next());
		System.out.println("CEP do " + end + "(sem pontos nem traços): ");
		e.setCep(in.nextInt());

		return e;
	}

	public void enviarTelegrama() throws IllegalAccessException {

		Scanner in = new Scanner(System.in);

		if (numCorrespondencias < MAX_CORRESPONDENCIAS) {
			Telegrama t = new Telegrama();

			t.setDestinatario(dados_Enderecavel("Destinatário"));
			t.setRemetente(dados_Enderecavel("Remetente"));

			System.out.println("Deseja confirmação de recebimento?\n <1> Sim \t <0> NÃO ");
			t.setConfirmacaoRecebimento(in.nextInt() == 1);
			System.out.println("Digite o número de páginas: ");
			t.setNumPaginas(in.nextInt());
			System.out.println("Digite o preço por página: ");
			t.setPrecoPorPagina(in.nextFloat());
			t.calcularPreco();
			
			correspondencias[numCorrespondencias] = t;
			numCorrespondencias++;
			System.out.println("Telegrama enviado com sucesso!");
		} else {
			System.out.println("Erro ao enviar telegrama!\n Tente novamente.");
		}
		throw new IllegalAccessException("Erro Enviar Telegrama!");
	}

	public void enviarCarta() throws IllegalAccessException {

		Scanner in = new Scanner(System.in);

		if (numCorrespondencias < MAX_CORRESPONDENCIAS) {
			Carta c = new Carta();

			c.setDestinatario(dados_Enderecavel("Destinatário"));
			c.setRemetente(dados_Enderecavel("Remetente"));
			System.out.println("Deseja confirmação de recebimento?\n <1> Sim \t <0> NÃO ");
			c.setConfirmacaoRecebimento(in.nextInt() == 1);
			System.out.println("Digite o peso: ");
			c.setPeso(in.nextInt());
			System.out.println("Digite o preço por grama: ");
			c.setPrecoPorGrama(in.nextFloat());
			c.calcularPreco();

			correspondencias[numCorrespondencias] = c;
			numCorrespondencias++;
			System.out.println("Carta enviada com sucesso!");
			System.out.println(c);
		} else {
			System.out.println("Erro ao enviar carta!\n Tente novamente.");
		}
		
	}

	public void enviarSedex() throws IllegalAccessException {

		Scanner in = new Scanner(System.in);
		if (numCorrespondencias < MAX_CORRESPONDENCIAS) {
			Sedex s = new Sedex();
			s.setDestinatario(dados_Enderecavel("Destinatário"));
			s.setRemetente(dados_Enderecavel("Remetente"));
			System.out
					.println("Deseja confirmação de recebimento?\n <1> Sim \t <0> NÃO ");
			s.setConfirmacaoRecebimento(in.nextInt() == 1);

			System.out.println("Digite o peso: ");
			s.setPeso(in.nextInt());
			System.out.println("Digite o peso por grama: ");
			s.setPesoPorGrama(in.nextFloat());
			System.out.println("Digite o comprimento: ");
			s.setComprimento(in.nextInt());
			System.out.println("Digite a altura: ");
			s.setAltura(in.nextInt());
			System.out.println("Digite a largura");
			s.setLargura(in.nextInt());
			s.calcularPreco();
			correspondencias[numCorrespondencias] = s;
			numCorrespondencias++;
			System.out.println("Sedex enviado com sucesso!");
		} else {
			System.out.println("Erro ao enviar Sedex!\n Tente novamente.");
		}
	}

	public void enviarSedex10() throws IllegalAccessException {

		Scanner in = new Scanner(System.in);

		if (numCorrespondencias < MAX_CORRESPONDENCIAS) {
			Sedex10 s10 = new Sedex10();
			s10.setDestinatario(dados_Enderecavel("Destinatário"));
			s10.setRemetente(dados_Enderecavel("Remetente"));
			System.out.println("Deseja confirmação de recebimento?\n <1> Sim \t <0> NÃO ");
			s10.setConfirmacaoRecebimento(in.nextInt() == 1);
			System.out.println("Digite o peso: ");
			s10.setPeso(in.nextInt());
			System.out.println("Digite o peso por grama: ");
			s10.setPesoPorGrama(in.nextFloat());
			System.out.println("Digite o comprimento: ");
			s10.setComprimento(in.nextInt());
			System.out.println("Digite a altura: ");
			s10.setAltura(in.nextInt());
			System.out.println("Digite a largura: ");
			s10.setLargura(in.nextInt());
			System.out.println("Digite a taxa: ");
			s10.setTaxa(in.nextFloat());
			s10.calcularPreco();
			correspondencias[numCorrespondencias] = s10;
			numCorrespondencias++;
			System.out.println("Sedex10 enviado com sucesso!");
		} else {
			System.out.println("Erro ao enviar Sedex10!\n Tente novamente.");
		}

	}

	public void listarTelegramas() {
		int i;
		for (i = 0; i < numCorrespondencias; i++) {
			System.out.println(correspondencias[i]);

		}
	}

	public void listarCartas() {
		int i;
		for (i = 0; i < numCorrespondencias; i++) {

			System.out.println(correspondencias[i]);
		}

	}

	public void listarSedex() {
		int i;
		for (i = 0; i < numCorrespondencias; i++) {

			System.out.println(correspondencias[i]);
		}
	}

	public void listarSedex10() {
		int i;
		for (i = 0; i < numCorrespondencias; i++) {

			System.out.println(correspondencias[i]);
		}
	}

	public float calcularFaturamento() {
		int i;

		float cont = 0;
		for (i = 0; i < numCorrespondencias; i++) {
			cont += correspondencias[i].calcularPreco();
		}
		for (i = 0; i < numCorrespondencias; i++) {
			cont += correspondencias[i].calcularPreco();
		}
		for (i = 0; i < numCorrespondencias; i++) {
			cont += correspondencias[i].calcularPreco();
		}
		for (i = 0; i < numCorrespondencias; i++) {
			cont += correspondencias[i].calcularPreco();
		}
		return cont;
	}

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);

		Correios cs = new Correios(MAX_CORRESPONDENCIAS);
		int op;
		do {
			System.out.println("\n\tCorreios\n");
			System.out.println("<1> Enviar Telegrama");
			System.out.println("<2> Enviar Carta");
			System.out.println("<3> Enviar Sedex");
			System.out.println("<4> Enviar Sedex10");
			System.out.println("<5> Listar Telegramas");
			System.out.println("<6> Listar Cartas");
			System.out.println("<7> Listar Sedex");
			System.out.println("<8> Listar Sedex10");
			System.out.println("<9> Calcular Faturamento");
			System.out.println("<0> Sair do Programa");
			System.out.print("Opção: ");
			switch (op = in.nextInt()) {
			case 1:
				System.out.println("\nEnviar Telegrama");
				try{
					cs.enviarTelegrama();
				}catch(IllegalAccessException e){
					System.out.println("Não há mais espaço no vetor!");
				}
				
				break;
			case 2:
				System.out.println("\nEnviar Carta");
				try{
					cs.enviarCarta();
				}catch(IllegalAccessException e){
					System.out.println("Não há mais espaço no vetor!");
				}
			
				break;
			case 3:
				System.out.println("\nEnviar Sedex");
				try{
					cs.enviarSedex();
				}catch(IllegalAccessException e){
					System.out.println("Não há mais espaço no vetor!");
				}
				break;
			case 4:
				System.out.println("\nEnviar Sedex10");
				try{
					cs.enviarSedex10();
				}catch(IllegalAccessException e){
					System.out.println("Não há mais espaço no vetor!");
				}
				break;
			case 5:
				System.out.println("\nListar Telegramas");
				cs.listarTelegramas();
				break;
			case 6:
				System.out.println("\nListar Cartas");
				cs.listarCartas();
				break;
			case 7:
				System.out.println("\nListar Sedex");
				cs.listarSedex();
				break;
			case 8:
				System.out.println("\nListar Sedex10");
				cs.listarSedex10();
				break;
			case 9:
				System.out.printf("\nCalcular Faturamento: R$ %.2f\n",
						cs.calcularFaturamento());
				break;
			case 0:
				break;
			default:
				System.out.println("\nOpção inválida!");
			}
		} while (op != 0);
	}

}

Do jeito que está acima, para cada método ele irá listar e calcular o faturamento do vetor inteiro! :s

Ah… esqueci de mencionar, o método calcular faturamento da classe Correspondência também é abstrato!

Desde já agradeço quem puder me auxiliar nesse projeto ^^

Não precisa saber. Use polimorfismo.

Obrigado pela resposta super rápida Vini ^^

Só para ver se eu entendi, por exemplo, em enviarTelegrama(), se eu quiser enviar um Telegrama do telegrama, ao invés de eu criar um objeto telegrama e depois inseri-lo no objeto correspondencias:

Telegrama t = new Telegrama();
t.setNumPaginas(in.nextInt());
correspondencias[numCorrespondencias] = t;  

eu poderia apenas fazer a linha abaixo, porque a classe Telegrama herda a Classe Correspondencia?

correspondencias[numCorrespondencia].setNumPaginas(in.nextInt()); // ??

Isso mesmo. Da mesma forma, se todas as classes tiverem o método enviar(), aí vc poderia enviar apenas fazendo:

for (Correspondencia c : correspondencias) { c.enviar(); }

O objeto mesmo se encarrega de saber se é um SEDEX, um SEDEX10, ou sei lá o que mais. :slight_smile:

Fiz isso, mas está dando este erro. Diz que o método não está definido em Correspondencia, como está dando erro se os métodos deveriam estar sendo herdados?

Erro:

The method setNumPaginas(int) is undefined for the type Correspondencia

Você poderia postar a classe Correspondencia? as vezes é algum detalhe que passou despercebido.

Claro ^^

Aí está:

package trab;


public abstract class Correspondencia {
	private Enderecavel remetente;
	private Enderecavel destinatario;
	private boolean confirmacaoRecebimento;
	


	public Correspondencia() {
	
	}

	public Correspondencia(int tam_end){
		remetente = new Enderecavel();
		destinatario = new Enderecavel();
		
	}
	
	public void setConfirmacaoRecebimento(boolean confirmacaoRecebimento) {
		this.confirmacaoRecebimento = confirmacaoRecebimento;
	}
	
	public String toString(){
		return "\n Remetente: " + remetente + "\n Destinatário: " + destinatario + "\n Confirmacao de Recebimento: " +
	 confirmacaoRecebimento;
	}

	public Enderecavel getRemetente() {
		return remetente;
	}

	public void setRemetente(Enderecavel remetente) {
		this.remetente = remetente;
	}

	public Enderecavel getDestinatario() {
		return destinatario;
	}

	public void setDestinatario(Enderecavel destinatario) {
		this.destinatario = destinatario;
	}

	public boolean isConfirmacaoRecebimento() {
		return confirmacaoRecebimento;
	}
	
	public abstract float calcularPreco();
	
}

Ah, acho que as coisas estão invertidas aí

A classe mais genérica é quem tem os membros que serão herdados pelas classes mais específicas. No seu caso o método setNumPaginas teria que estar definido em Correspondencia, para que SEDEX, SEDEX10 possam herdá-lo.

Mas Sedex e Sedex10 não precisam herdar nada da Classe Telegrama (como numPaginas), apenas de Correspondencia. O “setNumPaginas” é um atributo apenas da Classe Telegrama, que será usado apenas quando, na Classe Correios, eu quiser enviar ou listar um Telegrama.

Anexei o UML para facilitar a ajuda de vocês ^^


Ah, entendi… Faz sentido :slight_smile:

Então seu método tem que ser pensado melhor, porque cada correspondência tem coisas específicas.

O que você pode fazer (se for possível) é criar um método enviar (como o Vini disse acima) em Correspondencia, e cada subclasse o sobrescreve, implementando as coisas específicas, e na hora de enviar você faz como no exemplo do Vini

Sim até poderia fazer, na minha mente funcionaria… mas se eu criasse a método Enviar() na Classe correspondencia eu mudaria o UML… e sabe como é trabalho de facul =/

Estava pensando, se eu preciso referenciar os atributos das outras Classes em Correspondencia, eu não poderia criar, na Classe Correspondencia, um método correspondencia para cada Classe que herda dela?

Assim, se eu fizer a linha abaixo na classe Correios deveria funcionar, não?

correspondencias[numCorrespondencia].setNumPaginas(in.nextInt());

Eu acabei de tentar referenciar assim, com vários métodos Correspondencias, mas continua dando esse mesmo erro! =/

As classes Carta, Telegrama, Sedex e Sedex10 são quase idênticas, vou postar uma para vocês verem, de repente preciso fazer alguma referencia em algum lugar…

package trab;


public class Carta extends Correspondencia{
	int peso;
	float precoPorGrama;
	
		
	public Carta(int peso,float precoPorGrama){
		this.peso = peso;
		this.precoPorGrama = precoPorGrama;
		
	}
	
	public Carta() {
		
	}


	public int getPeso() {
		return peso;
	}


	public void setPeso(int peso) {
		this.peso = peso;
	}


	public float getPrecoPorGrama() {
		return precoPorGrama;
	}



	public void setPrecoPorGrama(float precoPorGrama) {
		this.precoPorGrama = precoPorGrama;
	}


	public float calcularPreco(){
		if(isConfirmacaoRecebimento())
		return peso * precoPorGrama + 1.20f;
		
		return peso * precoPorGrama;
	}
	
	public String toString(){
		return super.toString() + "\n Peso: " + peso + "\n Valor por Grama: " + precoPorGrama;
	}

	}	

Se você não puder alterar aí perde a graça, porque vai ter que ficar verificando tipo, e isso não fica muito bacana, fica mais ou menos assim:for(Correspondencia c : correspondencias){ if(c instanceof SEDEX){ SEDEX sedex = (SEDEX) c; // Faz o que tem que ser feito pra SEDEX; }else if(c instanceof Carta){ Carta carta = (Carta) c; // Faz o que tem que ser feito pra Carta; } // ... }

Vou implementar esses if’s com instanceof para ver se funciona, estou no trabalho então a noite posto aqui se funcionou ou não ^^

vlw

[quote=LeandroSMattos]Vou implementar esses if’s com instanceof para ver se funciona, estou no trabalho então a noite posto aqui se funcionou ou não ^^

vlw[/quote]

Esses ifs geralmente são gambi. O ideal é usar polimorfismo. Mesmo que seja mais difícil de entender e, inicialmente, te dê mais trabalho. O esforço compensa.

É, eu concordo, mas como ele disse é trabalho de faculdade e ele provavelmente não pode mudar o UML.

Vai ver o professor quer que eles façam a gambi pra depois mostrar o que o polimorfismo pode fazer :slight_smile:

Consegui, usei instanceof, mas também usei polimorfismo pois o vetor correspondencia, dependendo da correspondencia, irá assumir uma forma diferente ^^

Fiz assim:

public void listarCartas() {
		int i;
		for (i = 0; i < numCorrespondencias; i++) {
			if(correspondencias[i] instanceof Carta){ 
			System.out.println(correspondencias[i]);
			}
		}

	}

Muito obrigado a todos pelo auxílio! Foram de grande ajuda para sanar minhas dúvidas… vlw ^^