Search code examples
javasavestoring-data

How do I save a value through multiple classes in Java?


I am new to java and coding in general. I was trying to create a game as a small side project to mess around while waiting on my next assignments in my comp sci classes. I ran into a problem where when I call my classes at the start, the values are forgotten when the next one is called. For example, when I say I want to "Go to Office Building" to work and make some money for myself, the cash is gone when I "Go to the Bank" right after. How can I make it so the game remembers how much cash I had from when I worked? I've tried to wrap my head around serialization but it is very confusing. I was wondering if there was a better way to do it or if someone could explain to me how to do it. Many thanks to anyone who replies!

import java.util.Scanner;
public class Game {
   public static void main(String[] args) {

    Work work = new Work();
    Bank bank = new Bank();
    Scanner input = new Scanner(System.in);
    int process = 0;
    while (process == 0) {
        System.out.println("What would you like to do?");
        System.out.println("1) Go to the Bank");
        System.out.println("2) Go to Office Building");
        System.out.println("3) Exit Game");
        int response = input.nextInt();
        if (response == 1) {
            Bank.main(args);
        }
        if (response == 2) {
            Work.main(args);
        }
        if (response == 3) {
            process++;
        }
    }
}

}

The code above is where I call my other classes. Here are my other two main classes and their respective classes.

import java.util.Scanner;
public class Work extends Working {
public static void main(String [] args) {
    Working work = new Working();
    Bank bank = new Bank();
    Scanner input = new Scanner(System.in);
    int process = 0;
    int jobExperience = 0;

    while (jobExperience == 0 && process == 0) {
        System.out.println("Welcome! Would you like to apply for a job? Y/N:");
        String response = input.next();

        if (response.equalsIgnoreCase("Y")) {
            jobExperience++;
        }
        else {
            System.out.println("Alright, see you next time!");
            process++;
        }
    }

    while (process == 0) {
        System.out.println("Welcome! Would you like to work? Y/N:");
        String response = input.next();

        if (response.equalsIgnoreCase("Y")) {
            System.out.println("How many hours would you like to work? 1-8:");
            int hours = input.nextInt();

            if (hours >= 1 && hours <= 8) {
                work.setHours(hours);
                work.setJob(jobExperience);
                work.wageCalc();
                work.setPaycheck();
                bank.setCash(bank.getCash()+work.getPaycheck());
                work.printStatement();
                jobExperience++;
                process++;
            }
        }
        else {
            System.out.println("Alright, see you next time!");
            process++;
        }
    }
}

}

2nd Part to class Work:

public class Working {
double wage;
double hours;
double paycheck;
int job;

public double getHours() {
    return hours;
}

public void setHours(double hours) {
    this.hours = hours;
}

public double getWage() {
    return wage;
}

public void setWage(double wage) {
    this.wage = wage;
}

public int getJob() {
    return job;
}

public void setJob(int job) {
    this.job = job;
}

public void wageCalc() {
    if (getJob() == 1) {
        setWage(15);
    }
    if (getJob() == 2) {
        setWage(20);
    }
    if (getJob() == 3) {
        setWage(30);
    }
    if (getJob() == 4) {
        setWage(45);
    }
    if (getJob() == 5) {
        setWage(70);
    }
    if (getJob() >= 6) {
        setWage(100);
    }
}

public void setPaycheck() {
    paycheck = hours * wage;
}

public double getPaycheck() {
    return paycheck;
}

public void printStatement() {
    System.out.println("You worked " + getHours() + " hours at a pay rate of $" + getWage() + "/hr and earned $" + getPaycheck() + ".");
}

}

I want the Bank and Work classes to remember each other's values.

import java.util.Scanner;
public class Bank extends Banking {
public static void main(String[] args) {
    Banking bank = new Banking();
    Scanner input = new Scanner(System.in);
    int process = 0;

    System.out.println("Thank you for banking with us. How can we help you?");
    while (process == 0) {
        System.out.println();

        System.out.println("Press 'B' to check your balance.  Press 'D' to deposit money. Press 'W' to withdraw money. Press 'E' to exit.");
        String response = input.next();

        if (response.equalsIgnoreCase("B")) {
            System.out.println("Your bank balance is currently $" + bank.getBalance());
            System.out.println("You currently have $" + bank.getCash() + " in cash.");
        }

        if (response.equalsIgnoreCase("D")) {
            System.out.println("How much would you like to deposit?");
            double amount = input.nextDouble();
            if (bank.getCash() >= amount) {
                bank.setDeposit(amount);
                bank.Deposit();
                bank.setCash(bank.getCash() - amount);
                System.out.println("You have deposited $" + bank.getDeposit() + ".");
                System.out.println("Your new balance is $" + bank.getBalance());
            }
            else {
                System.out.println("Sorry, you do not have enough cash to deposit.");
            }
        }

        if (response.equalsIgnoreCase("W") && bank.getBalance() > 0) {
            System.out.println("How much would you like to withdraw?");
            double amount = input.nextDouble();

            if (amount < bank.getBalance()) {
                bank.setWithdraw(amount);
                bank.Withdraw();
                System.out.println("You have withdrawn $" + bank.getWithdraw() + ".");
                System.out.println("Your new balance is $" + bank.getBalance());
            }

            else {
                System.out.println("You do not have sufficient funds to withdraw");
                System.out.println("Your current balance is $" + bank.getBalance());
            }
        }

        else if (response.equalsIgnoreCase("W") && bank.getBalance() <= 0) {
            System.out.println("You do not have sufficient funds to withdraw");
        }

        if (response.equalsIgnoreCase("E")) {
            process = 2;
            System.out.println("Goodbye!");
        }
    }
}

}

Here is the second part to my Bank:

public class Banking {
private double balance;
private double withdraw;
private double deposit;
private double cash;

public void setCash(double cash) {
    this.cash = cash;
}

public double getCash() {
    return cash;
}

public void setBalance(double balance) {
    this.balance = balance;
}

public double getBalance() {
    return balance;
}

public void setWithdraw(double withdraw) {
    this.withdraw = withdraw;
}

public double getWithdraw() {
    return withdraw;
}

public void setDeposit(double deposit) {
    this.deposit = deposit;
}

public double getDeposit() {
    return deposit;
}

public void Withdraw() {
    balance = balance - withdraw;
}
public void Deposit() {
    balance = balance + deposit;
}

}


Solution

  • The short answer is, you need to pass some kind of "state" between your classes and they (optionally, depending on what they do) need to pass back new "state"

    How you do this comes down to the problem you're trying to solve, but you should start by looking at Passing Information to a Method or a Constructor and Returning a Value from a Method for a starting point.

    As an example, I'm going to do something which you might not like, but which will demonstrate the basic concepts.

    First, the "contracts". We need some way to "contain" the various things we want to track and define the operations they are willing to perform, for this, we start with some basic interfaces

    public interface Life {
        public int getExperience();
        public void addExperience(int experience);
    }
    
    public interface Job {
        public double getHours();
        public double getHourlyRate();
        public PayCheck getPayCheck();
    }
    
    public interface PayCheck {
        public int getExperienceGained();
        public double getAmount();
        public String getSummary();
    }
    
    public interface Bank {
        public double getBalance();
        public void deposit(PayCheck payCheck);
        public void deposit(double amount);
        public double withdraw(double amount);
        public String getSummary();
    }
    

    nb: You have no idea how much I want to have a mutable and non-mutable Life as not every one should be able to add experience

    Next, we need some actual implementations (normally I'd create abstract versions which define most of the common work, but this is a basic example, so I skipped those)

    public class DefaultLife implements Life {
        private int experience;
    
        @Override
        public int getExperience() {
            return experience;
        }
    
        @Override
        public void addExperience(int experience) {
            this.experience += experience;
        }
        
    }
    
    public class DefaultJob implements Job {
    
        private double hoursWorked;
        private double hourlyRate;
    
        public DefaultJob(Life life, double hoursWorked) {
            this.hoursWorked = hoursWorked;
            int experience = life.getExperience();
    
            if (experience <= 1) {
                hourlyRate = 15;
            } else if (experience == 2) {
                hourlyRate = 20;
            } else if (experience == 3) {
                hourlyRate = 30;
            } else if (experience == 4) {
                hourlyRate = 45;
            } else if (experience == 5) {
                hourlyRate = 70;
            } else {
                hourlyRate = 100;
            }
        }
    
        @Override
        public double getHours() {
            return hoursWorked;
        }
    
        @Override
        public double getHourlyRate() {
            return hourlyRate;
        }
    
        @Override
        public PayCheck getPayCheck() {
            double amount = getHours() * getHourlyRate();
            return new DefaultPayCheck(1, this);
        }
    }
    
    public class DefaultPayCheck implements PayCheck {
    
        private int experienceGained;
        private double amount;
        private Job job;
    
        public DefaultPayCheck(int experience, Job job) {
            this.experienceGained = experience;
            this.amount = job.getHourlyRate() * job.getHours();
            this.job = job;
        }
    
        @Override
        public int getExperienceGained() {
            return experienceGained;
        }
    
        @Override
        public double getAmount() {
            return amount;
        }
    
        public Job getJob() {
            return job;
        }
    
        @Override
        public String getSummary() {
            Job job = getJob();
            return "You worked " + job.getHours() + " hours @ $" + job.getHourlyRate() + " and earned $" + getAmount() + " and have earned and additional " + getExperienceGained() + " experience";
        }
    }
    
    public class DefaultBank implements Bank {
        
        private double balance;
    
        @Override
        public double getBalance() {
            return balance;
        }
    
        @Override
        public void deposit(PayCheck payCheck) {
            deposit(payCheck.getAmount());
        }
    
        @Override
        public void deposit(double amount) {
            balance += amount;
        }
    
        @Override
        public double withdraw(double amount) {
            // All your momey belong to us
            return 0;
        }
    
        @Override
        public String getSummary() {
            return "You have $" + balance + " in the bank";
        }
        
    }
    

    But why 😱?! Well, take a look at DefaultJob. It takes a reference to an instance of Life. It doesn't care how Life is implemented, only that what ever you pass it conforms the contact described by the interface...this is something that's very powerful.

    Now, if that's just making you too confused 🥴😵‍💫. You could remove all the interfaces and simply make use of the "default" classes, but you're losing a lot of potential opportunities (I'm mean, how many jobs can you think off? How many banks?)

    And finally, we need something to pull it altogether...

    Scanner scanner = new Scanner(System.in);
    
    Life life = new DefaultLife();
    Bank bank = new DefaultBank();
    
    boolean done = false;
    do {
        if (life.getExperience() == 0) {
            System.out.println("Welcome! Would you like to apply for a job? Y/N:");
            String response = scanner.nextLine();
    
            if ("Y".equalsIgnoreCase(response)) {
                life.addExperience(1);
            } else {
                System.out.println("Alright, see you next time!");
                done = true;
            }
        }
    
        if (!done) {
            System.out.println("Welcome to work!");
            boolean isValid = false;
            while (!isValid) {
                System.out.println("How many hours would you like to work? 1-8:");
                String input = scanner.nextLine();
                try {
                    int hours = Integer.parseInt(input);
                    if (hours < 1) {
                        System.out.println("Okay, see you next time!");
                        isValid = true;
                    } else if (hours > 0 && hours < 9) {
                        isValid = true;
                        Job job = new DefaultJob(life, hours);
                        PayCheck payCheck = job.getPayCheck();
                        System.out.println(payCheck.getSummary());
    
                        life.addExperience(payCheck.getExperienceGained());
                        double amount = payCheck.getAmount();
                        bank.deposit(payCheck);
                        System.out.println(bank.getSummary());
                    } else {
                        System.out.println(hours + " is not a valid number of hours!");
                    }
                } catch (NumberFormatException exp) {
                    System.out.println(input + " is not a valid value!");
                }
            }
        }
        System.out.println("Would you like to continue? [Y]");
        done = !"Y".equalsIgnoreCase(scanner.nextLine());
    } while (!done);
    

    Now, this is not the only way you could to do this (you could have the Job update the experience of Life itself, but that's an architectural decision)

    Runnable example

    And because it's always fun to try and paste seperate pieces of code together 😝

    import java.util.Scanner;
    
    public class GameOfLife {
    
        public static void main(String[] args) {
            new GameOfLife();
        }
    
        public GameOfLife() {
            Scanner scanner = new Scanner(System.in);
    
            Life life = new DefaultLife();
            Bank bank = new DefaultBank();
    
            boolean done = false;
            do {
                if (life.getExperience() == 0) {
                    System.out.println("Welcome! Would you like to apply for a job? Y/N:");
                    String response = scanner.nextLine();
    
                    if ("Y".equalsIgnoreCase(response)) {
                        life.addExperience(1);
                    } else {
                        System.out.println("Alright, see you next time!");
                        done = true;
                    }
                }
    
                if (!done) {
                    System.out.println("Welcome to work!");
                    boolean isValid = false;
                    while (!isValid) {
                        System.out.println("How many hours would you like to work? 1-8:");
                        String input = scanner.nextLine();
                        try {
                            int hours = Integer.parseInt(input);
                            if (hours < 1) {
                                System.out.println("Okay, see you next time!");
                                isValid = true;
                            } else if (hours > 0 && hours < 9) {
                                isValid = true;
                                Job job = new DefaultJob(life, hours);
                                PayCheck payCheck = job.getPayCheck();
                                System.out.println(payCheck.getSummary());
    
                                life.addExperience(payCheck.getExperienceGained());
                                double amount = payCheck.getAmount();
                                bank.deposit(payCheck);
                                System.out.println(bank.getSummary());
                            } else {
                                System.out.println(hours + " is not a valid number of hours!");
                            }
                        } catch (NumberFormatException exp) {
                            System.out.println(input + " is not a valid value!");
                        }
                    }
                }
                System.out.println("Would you like to continue? [Y]");
                done = !"Y".equalsIgnoreCase(scanner.nextLine());
            } while (!done);
        }
    
        public interface Life {
    
            public int getExperience();
    
            public void addExperience(int experience);
        }
    
        public interface Job {
    
            public double getHours();
    
            public double getHourlyRate();
    
            public PayCheck getPayCheck();
        }
    
        public interface PayCheck {
    
            public int getExperienceGained();
    
            public double getAmount();
    
            public String getSummary();
        }
    
        public interface Bank {
    
            public double getBalance();
    
            public void deposit(PayCheck payCheck);
    
            public void deposit(double amount);
    
            public double withdraw(double amount);
    
            public String getSummary();
        }
    
        public class DefaultLife implements Life {
    
            private int experience;
    
            @Override
            public int getExperience() {
                return experience;
            }
    
            @Override
            public void addExperience(int experience) {
                this.experience += experience;
            }
    
        }
    
        public class DefaultJob implements Job {
    
            private double hoursWorked;
            private double hourlyRate;
    
            public DefaultJob(Life life, double hoursWorked) {
                this.hoursWorked = hoursWorked;
                int experience = life.getExperience();
    
                if (experience <= 1) {
                    hourlyRate = 15;
                } else if (experience == 2) {
                    hourlyRate = 20;
                } else if (experience == 3) {
                    hourlyRate = 30;
                } else if (experience == 4) {
                    hourlyRate = 45;
                } else if (experience == 5) {
                    hourlyRate = 70;
                } else {
                    hourlyRate = 100;
                }
            }
    
            @Override
            public double getHours() {
                return hoursWorked;
            }
    
            @Override
            public double getHourlyRate() {
                return hourlyRate;
            }
    
            @Override
            public PayCheck getPayCheck() {
                double amount = getHours() * getHourlyRate();
                return new DefaultPayCheck(1, this);
            }
        }
    
        public class DefaultPayCheck implements PayCheck {
    
            private int experienceGained;
            private double amount;
            private Job job;
    
            public DefaultPayCheck(int experience, Job job) {
                this.experienceGained = experience;
                this.amount = job.getHourlyRate() * job.getHours();
                this.job = job;
            }
    
            @Override
            public int getExperienceGained() {
                return experienceGained;
            }
    
            @Override
            public double getAmount() {
                return amount;
            }
    
            public Job getJob() {
                return job;
            }
    
            @Override
            public String getSummary() {
                Job job = getJob();
                return "You worked " + job.getHours() + " hours @ $" + job.getHourlyRate() + " and earned $" + getAmount() + " and have earned and additional " + getExperienceGained() + " experience";
            }
        }
    
        public class DefaultBank implements Bank {
    
            private double balance;
    
            @Override
            public double getBalance() {
                return balance;
            }
    
            @Override
            public void deposit(PayCheck payCheck) {
                deposit(payCheck.getAmount());
            }
    
            @Override
            public void deposit(double amount) {
                balance += amount;
            }
    
            @Override
            public double withdraw(double amount) {
                // All your momey belong to us
                return 0;
            }
    
            @Override
            public String getSummary() {
                return "You have $" + balance + " in the bank";
            }
    
        }
    }