9.1 Trabalhando com multiplicidade

Nosso CarrinhoDeCompras só está fazendo uma parte de seu trabalho, que é acumular o valor total dos produtos adicionados. Também precisaremos ter um atributo nessa classe para guardar uma referência a todos esses Produtos adicionados.

Poderíamos adicionar um número limitado de atributos do tipo

Produto, como:

public class CarrinhoDeCompras {
java
private double total; private Produto produto1; private Produto produto2; private Produto produto3;
 
private Produto produto4; II ...
 
II demais metodos da classe
 
}
 

Deixando esses atributos com o tipo Produto, no lugar de um Livro

ou Revista por exemplo, o polimorfismo nos daria a flexibilidade de adicionar qualquer classe que implemente essa interface Produto. Mas, fora isso, nosso código não está nem um pouco flexível! Além de termos um número limitado de produtos, no método adiciona precisaríamos fazer várias condições para verificar qual atributo está disponível antes de adicionar:

public class CarrinhoDeCompras {
java
private double total; private Produto produto1; private Produto produto2; private Produto produto3; private Produto produto4; II..
 
java
public void adiciona(Produto produto) { System.out.println("Adicionando: " + produto);

if (this.produto1 != null) { this.produto1 = produto;

}

else if (this.produto2 != null) { this.produto2 = produto;

}

else if (this.produto3 != null) { this.produto3 = produto;

}

else if (this.produto4 != null) { this.produto4 = produto;

}

II …

else {

System.out.println("Nao tem mais espa<os"); return;

}

total += produto.getValor();

}

}

Imagine como seria para mostrar os detalhes dos produtos adicionados, novamente precisaríamos repetir esses ifs todos com as condicionais. Esse código seria bem difícil de manter, quase inviável. Além disso, quantos atributos do tipo Produto um CarrinhoDeCompras teria? 10? 20? Isso vai depender muito do cliente, ele pode estar comprando um único livro ou uma coleção completa e diversos outros produtos.

Criando um array de Produto

Evitamos até agora trabalhar com esse recurso, mas, como vimos no primeiro capítulo, podemos resolver esse problema trabalhando com arrays! Não lembra o que é isso? Dê uma boa olhada novamente na declaração do método main de qualquer uma de suas classes:

public static void main(String[] args) {

// seu c6digo aqui

}

Repare que ele recebe um array de Strings como parâmetro! O

String[] args.

Podemos utilizar essa mesma estratégia em nosso CarrinhoDeCompras, basta remover todos estes atributos do tipo Produto e declarar um único array. Como fazer isso? É bem simples, basta adicionar [] depois do tipo e pronto. Nosso CarrinhoDeCompras vai ficar assim:

public class CarrinhoDeCompras {
java
private double total; private Produto[J produtos;
 
java
public void adiciona(Produto produto) {

// precisamos adicionar no array

}

}

Um array é um tipo, um objeto. Isso significa que, antes de fazer qual-

quer operação com o atributo produtos, precisaremos instanciá-lo. A sintaxe é um pouco diferente, mas é bem simples:

public class CarrinhoDeCompras {
java
private double total;
 
private Produto[] produtos = new Produto[10];
 
//..
 
}
 

Note que ao criar o array fomos obrigados a informar o seu tamanho!

Neste caso, criamos um array de 10 posições. Poderíamos sim receber a quantidade de Produtos no construtor da classe ou criar um método setProdutos, isso a deixaria um pouco mais flexível. Mas a princípio, deixaremos o CarrinhoDeCompras assim, limitado a 10 produtos.

Agora que estamos trabalhando com um array, precisamos mudar o método adiciona. Podemos fazer algo como:

public void adiciona(Produto produto) { System.out.println("Adicionando: " + produto); this.produtos[1] = produto;

this.total += produto.getValor();

}

Note que estamos adicionando todos os produtos na mesma posição do

array, na posição 1. Um detalhe muito importante é que a posição 1 é a segunda posição do array, e não a primeira. Isso acontece pois seus índices vão de 0 (zero) até seu tamanho -1, ou seja, como criamos um array de 10 posições, ele vai de0a 9.

Uma alternativa seria mudar a assinatura do método adiciona para receber um int indice como parâmetro, mas deixar esse controle na mão

de quem vai chamar o método pode não ser muito interessante, isso abriria caminho para chamar o método duas vezes com o mesmo indice e um elemento sobrescrever o outro, por exemplo.

No lugar disso podemos criar um atributo contador que é incrementado a cada nova adição, veja:

public class CarrinhoDeCompras {
java
private double total;
 
private Produto[] produtos = new Produto[10]; private int contador = 0;
 
java
public void adiciona(Produto produto) { System.out.println("Adicionando: " + produto); this.produtos[contador] = produto;

contador ++;

this.total += produto.getValor();

}

public double getTotal() { return total;

}

}

Problema resolvido! Sim, ainda estamos deixando passar algumas situ-

ações, como por exemplo tentar adicionar mais produtos do que cabe dentro de nosso array. E se eu tentar adicionar 11 produtos? Precisamos tratar isso de alguma forma. Por enquanto, o código ficará assim, mas em breve voltaremos para refatorar e cuidar desse tipo de detalhe da classe CarrinhoDeCompras.

ARRAY OU C OLLECTIONS?

Os arrays estao tirando o seu sono? Trabalhar com arrays pode nem sempre ser taosimples e intuitivo. Isso e natural, afinal e um recurso

carregado de uma serie de conceitos e uma sintaxe um pouco diferente. Mais afrente conheceremos uma forma mais interessante dese trabalhar

com coles:oes em Java, com a API de Collections!

Exibindo os Produtos adicionados

Devemos agora criar um metodo getProdutos para retornar o array deProduto epossibilitar aexibis:ao dosdetalhes decada produto adicionado no CarrinhoDeCompras. Um possivel uso desse metodo seria exibirmos o valor de cada Produto depois de adicionado:

Produto[] produtos = carrinho.getProdutos(;)

for(int i : = O; i < produto.slength; i++) { Produto produto = produtos[i;]

if (produto != null) {

Syste.mout.println(produt.goetValor());

}

}

Repare queestamos verificando seo Produto nao e nulo antes de tentar imprimir seu valor, afinal temos um array com 10 posis:oes mas s6 esta­ mos ocupando duas. Ao executar esse c6digo no RegistroDeVendas, o resultado sera parecido com:

Valor agora e 53.91 Adicionando:

br.com .casado codigo.livraria.produtos.LivroFisico@4f23c557 Adicionando:

br.com.casadocodigo.livraria.produtos.Ebook@2l a33b44 Total 83.81

53.91

29.9

0 c6digo esta funcionado da forma como esperamos, mas um simples erro poderia causar problemas. Observe nosso f or , ele faz a condic;:ao i

< p r od ut o s . l e ngt h. 0 atributo l e ngt h de um array carrega o seu

tamanho total, portanto neste exemplo sera10. 0 que aconteceria se, no lugar de <, tivessemos escrito ? Fac;:a a alterac;:ao e rodeo c6digo para ver o resultado! Sera algo parecido com:

Valor agora e 53.9 1 Adicionando:

br.com.casadocodigo.livr aria.prod utos.LivroFisico@4f23c557 Adicionado:

br.com.casadocodigo.livraria.produtos.Ebook@2la33b44

Total 83.81

53.91

29.9

Exception in thread “main” java.lang.ArrayindexOutOfBoundsException:

at br.com.casadocodig.olivraria.testes

.RegistroDeVenda.smain(RegistroDeVenda.sjava:38)

Note que, ao adicionar o operador de = na condic;:ao, estamos tentando iterar em uma posic;:ao (10) fora do limite do ar r a y, que vai de o a 9. Maso que toda essa mensagem significa? Pode ser a primeira ou a milesima vez que ve uma mensagem como essa, mas a partir de agora passaremos a chama-la pelo seu nome. Essa e uma stacktrace!

O enhanced-for do Java

Desde o Java 1.5, é possível iterar em um array (ou qualquer outro Iterable, que veremos nos próximos capítulos) com uma sintaxe um pouco diferente. No lugar de:

for(int i : = O; i < produtos.length; i++) { Produto produto = produtos[i];

if (produto != null) { System.out.println(produto.getValor());

}

}

Podemos fazer o mesmo da seguinte forma, com o enhanced-for:

for(Produto produto : produtos) { if (produto != null) {

System.out.println(produto.getValor());
python

⬅️ Capítulo Anterior | Próximo Capítulo ➡️