[RESOLVIDO] Dificuldade com arrayList, herança e polimorfismo tudo em uma única classe

Estou tentando criar uma lista genérica de clientes, onde posso adicionar pessoasFisicas e pessoasJuridicas.

Dentro da classe clientes possuo os atributos nome, lista de endereços e limite de crédito.
A classe pessoaFisica herda de cliente os atributos acima citados além de possuir o atributo cpf.
A classe pessoaJuridica herda de cliente seus atributos e possui também, nomeFantasia e cnpj.

O problema que está acontecendo é o seguinte: na hora que cadastro mais de uma pessoa física por exemplo e puxo o relatório, me vem a lista de endereços inteira ao invés de vim a lista da pessoa de cada posição do ArrayList de clientes. Como resolvo isso?

public void cadastrar() {
int op, resp;
System.out.println("\n==[Cadastro de clientes]==");
System.out.println(“Digite 1 para cadastrar pessoa fisica.”);
System.out.println(“Digite 2 para cadastrar pessoa juridica.”);
System.out.print("=> ");
op = input.nextInt();

	switch (op) {
	case 1:
		System.out.println("\n==[Pessoa fisica]==");
		System.out.print("Informe o nome: ");
		nome = inputs.nextLine();
		
		do {
			listaEndFisica.add(retornaUmEndereco());
			System.out.println("Continuar cadastrando endereços? 1-Sim/0-Não");
			resp = input.nextInt();
		} while (resp != 0);
		
		System.out.print("Informe o limite de crédito: ");
		limiteCredito = input.nextDouble();
		System.out.print("informe o cpf: ");
		cpf = inputs.nextLine();
		PessoaFisica pessoaFisica = new PessoaFisica(nome, listaEndFisica, limiteCredito, cpf);
		listaCliente.add(pessoaFisica);
		System.out.println("\nPessoa fisica adicionado com sucesso! ");
		break;
	case 2:

		System.out.println("\n==[Pessoa Juridica]==");
		System.out.print("Informe o nome: ");
		nome = inputs.nextLine();
		
		do {
			listaEndJuridica.add(retornaUmEndereco());
			System.out.println("Continuar cadastrando endereços? 1-Sim/0-Não");
			resp = input.nextInt();
		} while (resp != 0);
		
		System.out.print("Informe o limite de crédito: ");
		limiteCredito = input.nextDouble();
		System.out.print("Informe o nome fantasia: ");
		nomeFantasia = inputs.nextLine();
		System.out.print("Informe o cnpj: ");
		cnpj = inputs.nextLine();
		PessoaJuridica pessoaJuridica = new PessoaJuridica(nome, listaEndJuridica, limiteCredito, nomeFantasia, cnpj);
		listaCliente.add(pessoaJuridica);
		System.out.println("\nPessoa juridica adicionado com sucesso! ");
		break;
	default:
		System.out.println("opção inválida! ");
	}

}

public void relatorio() {
if (listaCliente.isEmpty()) {
System.out.println(“Não existem clientes cadastrados! “);
} else {
for (Cliente c : listaCliente) {
if (c instanceof PessoaFisica) {
System.out.println(”\n-=[Pessoas Fisicas]=-”);
System.out.println(“Nome: " + c.getNome());
System.out.println(”-=[Endereço(s) Associado(s)]<-");
for (Endereco end : listaEndFisica) {
System.out.println("Logradouro: " + end.getLogradouro());

				}
				System.out.println("Limite de crédito: " + c.getLimiteDeCredito());
				System.out.println("Cpf: " + ((PessoaFisica) c).getCpf());

			} else if (c instanceof PessoaJuridica) {
				System.out.println("\n-=[Pessoas Juridicas]=-");
				System.out.println("Nome: " + c.getNome());
				System.out.println("-=[Endereço(s) Associado(s)]<-");
				for (Endereco end : listaEndJuridica) {
					end.getLogradouro();
					System.out.println("Logradouro: " + end.getLogradouro());

				}
				System.out.println("Limite de crédito: " + c.getLimiteDeCredito());
				System.out.println("Nome fantasia: " + ((PessoaJuridica) c).getNomeFantasia());
				System.out.println("Cnpj: " + ((PessoaJuridica) c).getCnpj());
			}
		}

	}
}

Sem%20t%C3%ADtulo

Talvez fosse interessante encapsular quem é pessoa Física ou Jurídica em suas próprias listas.

No momento do cadastro, uma instância de Física ou Jurídica seria utilizada. Esta instância guardaria suas próprias características e depois é adicionada na sua lista correspondente.

No momento do relatório, ao varrer a lista, cada cliente terá suas próprias informações.

Em resumo seria criar uma lista para Fisica e uma para Juridica, adicionando ambas numa lista de clientes é isso mesmo?

Como eu identificaria depois, quem é quem na lista de clientes?

Ah, sim.

Neste caso, poderia não criar as listas como citei acima.
Porém, no momento do cadastro, permanecendo com as instâncias correspondentes para cada Física/Jurídica e depois jogando na lista de clientes.

vamos la

eu acho que isso é um caso para se lidar com Polimorfismo.

quando vc tem instanceof no seu codigo, vc provavelmente vazou detalhes da implementação interna dos seus objetos. antigamente isso era necessario pois sem generics vc tinha que lidar com tipos muito basicos e um cast errado poderia dar ruim, mas estamos no ano 2018 e o futuro ja chegou.

Vamos dizer que vc tem um tipo Pessoa e duas implementações: PessoaFisica ou PessoaJuridica

vc tem relações do tipo é um, afinal

PessoaFisica é um(a) Pessoa
PessoaJuridica é um(a) Pessoa

e vc pode fazer magicas como

Pessoa p;
if ( cadastras pessoa fisica ) {
  p = new PessoaFisica();
} else {
  ...
}

e por ai vai.

porem vc tem que mostrar essas coisas e informações… que tal o tipo Pessoa definir um metodo getInfo() que retorna uma String?
e esse retorno ser exatamente o texto que vc quer imprimir?
e vc faz apenas

System.out.println( p.getInfo() );

seus problemas estão resolvidos. Afinal de contas, o codigo que vai ser executado será o codigo do tipo que vc criou a instancia, não do tipo da variavel. isso é o que a gente chama de Polimorfismo: vc tem um mesmo metodo com diferentes comportamentos, adequados a cada tipo que vc definiu.

( isso não é verdade para metodos Static - mas isso são outros 500 )

vc tem 2 formas bacanas de fazer isso

  1. Pessoa é uma interface, que ambas as classes implementam ( via implements keyword)
  2. Pessoa é uma classe abstrata, que tem a definição do metodo getInfo() como o exemplo abaixo e ambas as classes extendem essa classe ( via extends keyword )
public abstract class Pessoa {
   public abstract String getInfo();
   ...
}

tem diferença? sim. uma classe pode implementar diversas interfaces enquanto uma classe abstrata vc tem as limitações ja conhecidas.

escolha com sabedoria.

1 curtida

Conseguir resolver o problema apenas alterando o for each. Percebi que estava utilizando o mesmo array de endereços da classe cliente para exibir os dados, quando deveria na verdade percorrer o array de endereços de cada cliente.

Antes:
if ( cliente instanceof PessoaFisica) {
for (Endereco end : listaEnderecoFisicas) {

}
}

Agora:

if ( cliente instanceof PessoaFisica) {
for (Endereco end : c.getEndereco()) {

}
}