Duvidas com metodos de desconto

Boa noite a todos!

De já, adianto que sou iniciante. Muito iniciante :grin: .

Estou com um problema em um programa de treino que estou desenvolvendo.
Vou expor o codigo aqui e em seguida, comentar o que esta acontecendo:

================

package entities;

public class Fabrica {

private Integer camisaP = 10;
private Integer camisaM = 15;
private Integer camisaG = 20;
private double total;
private Descontos desconto;

public Integer getCamisaP() {
	return camisaP;
}

public void setCamisaP(Integer camisaP) {
	this.camisaP = camisaP;
}

public Integer getCamisaM() {
	return camisaM;
}

public void setCamisaM(Integer camisaM) {
	this.camisaM = camisaM;
}

public Integer getCamisaG() {
	return camisaG;
}

public void setCamisaG(Integer camisaG) {
	this.camisaG = camisaG;
}

public Double quantidadesCamisetas(int qtdCP, int qtdCM, int qtdCG) {
	total = (camisaP * qtdCP) + (camisaM * qtdCM) + (camisaG * qtdCG);
	return total;
}

public double getTotal() {
	return total;
}

@Override
public String toString() {
	return "Total: " + total + " R$. /nTotal com descontos: " + desconto.desconto();

================

package entities;

public class Descontos {

private double desconto10 = 0.1;
private double desconto20 = 0.2;
private double desconto30 = 0.3;
private Fabrica fabrica;
private double descontoTotal;

public double desconto() {

	double totalGeral = fabrica.getTotal();
	if (totalGeral <= 100.0) {
		descontoTotal = totalGeral / desconto10;
	} else if (totalGeral <= 150.00) {
		descontoTotal = totalGeral / desconto20;
	} else {
		descontoTotal = totalGeral / desconto30;
	}
	return descontoTotal;
}

public String toString() {
	return "." + descontoTotal;
}

}

================

package entities;

import java.util.Locale;
import java.util.Scanner;

public class Program {
public static void main(String[] args) {

	Locale.setDefault(Locale.US);
	Scanner sc = new Scanner(System.in);
	
	Fabrica fabrica = new Fabrica();
	
	System.out.println("Bem vindo a loja de camisetas!");
	System.out.println("Digite o total de camisas por tamanho desejadas:");
	System.out.print("Camisa P: ");
	int p = sc.nextInt();
	System.out.print("Camisa M: ");
	int m = sc.nextInt();
	System.out.print("Camisa G: ");
	int g = sc.nextInt();
	
	fabrica.quantidadesCamisetas(p, m, g);
	
	System.out.println(fabrica);
	
	sc.close();
}

}

=============ERRO=========

Exception in thread “main” java.lang.NullPointerException: Cannot invoke “entities.Descontos.desconto()” because “this.desconto” is null
at entities.Fabrica.toString(Fabrica.java:46)
at java.base/java.lang.String.valueOf(String.java:3365)
at java.base/java.io.PrintStream.println(PrintStream.java:1047)
at entities.Program.main(Program.java:25)

==========

Este erro acontece quando eu tento usar o metodo de desconto. Más não consegui intender exatamente o que pode estar errado. (muito leigo por sinal);

Alguem poderia me ajudar? Desculpem o incômodo. :pensive:

Na sua classe Fabrica, vc declarou o campo desconto, mas não o inicializou.
Tente assim:
private Descontos desconto = new Descontos();

Fiz isso.
Agora dá outro erro informando que o fabrica.getTotal(); é nulo.

==========

Cannot invoke “entities.Fabrica.getTotal()” because “this.fabrica” is null

É a mesma coisa.
Na classe Descontos tem um campo fabrica que não foi inicializado.

1 curtida

Sua classe Fabrica possui um atributo do tipo Descontos.
Sua classe Descontos possui um atributo do tipo Fabrica.
Essa modelagem está estranha, porque ambas dependem entre si?

1 curtida

da um erro pior ainda se eu instanciar

Na fabrica, coloquei para usar no toString();.

=========

@Override
public String toString() {
return "Total: " + getTotal() + " R$. /nTotal com descontos: " + desconto.desconto();
}

Um stackoverflow?

Fabrica depende de Descontos e Descontos depende de Fabrica.
Ao instanciar Fabrica, instancia Descontos, que instancia Fabrica, etc, etc loop infinito.

Melhor repensar o modelo como o @staroski comentou.

estou reescrevendo. Vamos ver no que dá

Uma sugestão é você tentar entender porque você precisa do objeto Fabrica em Descontos e porque você precisa do objeto Descontos em Fabrica.

No primeiro caso: por que existe um objeto Fabrica em Descontos?
Lendo seu código, o método desconto usa fabrica para pegar o total:

double totalGeral = fabrica.getTotal();

Uma maneira simples de simplificar isso é ao invés de ter um atributo Fabrica no objeto Desconto, você pode passar fabrica como parâmetro:

public double desconto(Fabrica fabrica) {

	double totalGeral = fabrica.getTotal();
	if (totalGeral <= 100.0) {
		descontoTotal = totalGeral / desconto10;
	} else if (totalGeral <= 150.00) {
		descontoTotal = totalGeral / desconto20;
	} else {
		descontoTotal = totalGeral / desconto30;
	}
	return descontoTotal;
}

A lógica fica igual, e na hora que você for chamar o método (de dentro da fábrica) é só fazer:

return "Total: " + total + " R$. /nTotal com descontos: " + desconto.desconto(this);
```

fiz isso.

agora da este erro:

==================

Exception in thread “main” java.lang.NullPointerException: Cannot invoke “entities.Descontos.desconto(entities.Fabrica)” because “this.desconto” is null
at entities.Fabrica.toString(Fabrica.java:51)
at java.base/java.lang.String.valueOf(String.java:3365)
at java.base/java.io.PrintStream.println(PrintStream.java:1047)
at Program.main(Program.java:27)

Tive uma ideia, mas não funcionou.

Coloquei que a classe Descontos extendia Fabrica, tirei Fabrica de parametro do metodo e puxei o .getTotal direto.

Da o mesmo erro…

Sei que poderia fazer isso direto na propria classe, mas a possibilidade de fazer de outra classe me deixou curioso. E resolver este problema pode me ser util no futuro…

forma de fazer na mesma classe fabrica:

===============

Double desconto;
Public void setDesconto(Double desconto){this.desconto=desconto};
Public Double getDesconto(){return desconto};
// para descontos em casas decimais, sendo 10% = 0,1
Public Double valorFinal(){
return (valordoProduto*desconto);
};

Segue seu codigo, fiz apenas as modificações para que funcione sem validar nada de calculos ou regras. Compare com o seu original e entenda as diferenças. ( leve em consideração que existem inumeras maneiras de fazer.)

//Classe descontos

public class Descontos {

private static double	desconto10	= 0.1;
private static double	desconto20	= 0.2;
private static double	desconto30	= 0.3;
private static double	descontoTotal;

public static double desconto(double totalGeral) {

	if (totalGeral <= 100.0) {
		descontoTotal = totalGeral / desconto10;
	} else if (totalGeral <= 150.00) {
		descontoTotal = totalGeral / desconto20;
	} else {
		descontoTotal = totalGeral / desconto30;
	}
	return descontoTotal;
}

public String toString() {
	return "." + descontoTotal;
}
}

//Classe Fabrica

public class Fabrica {

private Integer	camisaP	= 10;
private Integer	camisaM	= 15;
private Integer	camisaG	= 20;
private double	total;

public int getCamisaP() {
	return camisaP;
}

public void setCamisaP(int camisaP) {
	this.camisaP = camisaP;
}

public Integer getCamisaM() {
	return camisaM;
}

public void setCamisaM(int camisaM) {
	this.camisaM = camisaM;
}

public Integer getCamisaG() {
	return camisaG;
}

public void setCamisaG(int camisaG) {
	this.camisaG = camisaG;
}

public void quantidadesCamisetas(int qtdCP, int qtdCM, int qtdCG) {
	total = (camisaP * qtdCP) + (camisaM * qtdCM) + (camisaG * qtdCG);
	setTotal(total);
}

public double getTotal() {
	return total;
}

@Override
public String toString() {
	return "Total: " + total + " R$. /nTotal com descontos: " + Descontos.desconto(getTotal());
}

public void setTotal(double total) {
	this.total = total;
}
}

//Classe Program

import java.util.Locale;
import java.util.Scanner;

 public class Program {
public static void main(String[] args) {

	Locale.setDefault(Locale.US);
	Scanner sc = new Scanner(System.in);

	Fabrica fabrica = new Fabrica();

	System.out.println("Bem vindo a loja de camisetas!");
	System.out.println("Digite o total de camisas por tamanho desejadas:");
	System.out.print("Camisa P: ");
	int p = sc.nextInt();
	System.out.print("Camisa M: ");
	int m = sc.nextInt();
	System.out.print("Camisa G: ");
	int g = sc.nextInt();

	fabrica.quantidadesCamisetas(p, m, g);

	System.out.println(fabrica);

	sc.close();
}
}

Espero qeu ajude a entender.

1 curtida

No mundo real faz sentido você dizer que um desconto é uma fábrica?
Se não fizer, então não faz sentido a classe Descontos estender a classe Fabrica.

Caramba… quanto erro tinha nesse meu codigo…

fiz dessa forma ai e funcionou. mudou bastante coisa!

aos poucos vou me habituando :grin:

Muito obrigado!