/* * Savings.java * * Created on August 16, 2002, 4:50 PM * * Right now interest is credited based on balance at time of crediting, * there is no keeping track of day to day balances or average daily balance */ package bank; import SortSearchEtc.Sorts; import java.util.Random; /** * * @author mike */ public class Savings extends Account { private double intYTD = 0; // interest rate for savings accounts public static double intRate = 0.03; /** * Creates a default new instance of Savings */ public Savings() { super(); intYTD = 0; } /** * Creates a new instance of Savings given a pin and balance */ public Savings(String pin, double bal) { super(pin,bal); intYTD = 0; } /** * Creates a new instance of Savings given an account number, pin and balance */ public Savings(String acct, String pin, double bal) { super(acct,pin,bal); intYTD = 0; } // dont know if we need a constructor that sets intYTD /** * pay interest into the calling Account based on the number of days * paying interest for (also, the class knows the interest rate) * Return: amount of interest paid */ public double payInterest (int numDays) { if (numDays <= 0) { System.out.println("ERROR - invalid number of days"); // no interest if no days or fewer return 0; } // daily interest rate is annual interest rate reduced by // proportion of days paying for double intAmt = balance * (intRate * (numDays / 365.0)); // update account balance and interest year to date balance += intAmt; intYTD += intAmt; return intAmt; } /** * MAR - I think the above is better * pay interest into the calling Account based on the number of days * paying interest for (also, the account knows the interest rate) * Return: whether interest is paid */ public boolean payInterestfirstVersion (int numDays) { if (numDays <= 0) { System.out.println("ERROR - invalid number of days"); return false; } double intAmt = balance * (intRate * (numDays / 365.0)); // update account balance and interest year to date balance += intAmt; intYTD += intAmt; return true; } /** * process month end - pay interest into the calling Account * default version - pays based on 30 day months * Return: new balance */ public double processMonthEnd() { double interest = payInterest(30); return getBal(); } /** * process month end - pay interest into the calling Account * default version - pays based on days in month - passed * Return: new balance */ public double processMonthEnd(int days) { double interest = payInterest(days); return getBal(); } /////////////////////////////////////////////////////////////////// // Inspectors /////////////////////////////////////////////////////////////////// /** * report the year to date interest */ public double getIntYTD() { return intYTD; } /** * we need a way of determining the interest rate * Static - since interest rate is static - once per class */ public static double getIntRate () { return intRate; } /** * Override Account's toString */ public String toString() { String res = super.toString(); res = res + " intYTD: " + intYTD; return res; } /////////////////////////////////////////////////////////////////// // Mutators /////////////////////////////////////////////////////////////////// /** * change the year to date interest */ public void setIntYTD(double amt) { intYTD = amt; } /** * reset the year to date interest back to zero */ public void resetIntYTD() { intYTD = 0; } /** * we need a way of setting the interest rate * Static - since interest rate is static - once per class */ public static void setIntRate (double rate) { intRate = rate; } /////////////////////////////////////////////////////////////////// // Test Driver /////////////////////////////////////////////////////////////////// /** * @param args the command line arguments * little test driver */ public static void main (String args[]) { Random generator = new Random(); Savings all[] = new Savings[10]; // define array of 10 savings accounts // actually create the accounts // Significant Java difference - the array itself is just a reference really for (int cnt = 0; cnt < 10; cnt++) { // assign a pin randomly - generated random integer and convert to string int rand = generator.nextInt(10000); String newPin = Integer.toString(rand); all[cnt] = new Savings(newPin,0); } // display the accounts System.out.println("All accounts: "); for (int cnt = 0; cnt < all.length; cnt++) { System.out.println(all[cnt].toString()); } ///////// Don't do the below (or at least don't show how it works) until we cover interfaces // try sorting array Sorts.insertSort(all); // display the accounts System.out.println("Sorted accounts: "); for (int cnt = 0; cnt < all.length; cnt++) { System.out.println(all[cnt].toString()); } boolean ok; // do some deposits for (int cnt = 0; cnt < all.length; cnt++) { // deposit some random amount up to $1000 double dep = (double) generator.nextInt(1000); ok = all[cnt].deposit(dep); System.out.println("#" + cnt + " " + all[cnt]); } // do some withdrawals for (int cnt = 0; cnt < all.length; cnt++) { // withdraw some random amount up to $100 double dep = (double) generator.nextInt(100); ok = all[cnt].withdraw(dep); System.out.println("withdrawal#" + cnt + " " + all[cnt]); } // process end of month double newAmt; for (int cnt = 0; cnt < all.length; cnt++) { // credit interest for a 30 day month newAmt = all[cnt].processMonthEnd(30); System.out.println("end month#" + cnt + " " + all[cnt]); } // mess around with type conversions involving inheritance Savings temp = new Savings("1234", 50.00); temp.deposit(100); temp.withdraw(75); Account tempA = temp; // you can always make a more general object // hold a more specific one // in this case all Savings accounts are // Accounts, so can hold account info tempA.deposit(100); tempA.withdraw(75); // to go the other way - make a specific object hold a general one // you need an explicit cast // - An account may not be a savings account, so may not be // appropriate to convert to a savings account - so // programmer must swear that that's what they want to do Savings tempS = (Savings) tempA; // Savings tempS = tempA; // error - incompatible types tempS.processMonthEnd(30); // because of assignments, these are all the same object, with same info // but even tempA, which is an Account, uses Savings' toString // since it really is a Savings Account - yet if you try to // processMonthEnd on tempA, you get a compile error System.out.println("temp: " + temp); System.out.println("tempA: " + tempA); System.out.println("tempS: " + tempS); Account junk = new Account("3232", 50.0); //Savings junkS = (Savings) junk; // gets ClassCastException - cannot cast something to something it is not System.out.println("junk: " + junk); //System.out.println("junkS: " + junkS); // use instanceof to ensure that object can be cast - to avoid exception if (junk instanceof Savings) { Savings junkS = (Savings) junk; System.out.println("junkS: " + junkS); } if (tempA instanceof Savings) { Savings tempS2 = (Savings) tempA; System.out.println("tempS2: " + tempS2); } // mess with true polymorphism // see different versions of toString run // temp was declared as a Savings account, and is one - easy System.out.println("Savings temp: " + temp); // junk was declared as an Account, and is one - easy System.out.println("Account junk: " + junk); // tempA was declared as an Account, references a Savings // - at run time determined to be Savings - get intYTD System.out.println("Savings tempA: " + tempA); // cannot declare something to be savings and have it reference // something that is really just an Account - gets ClassCastException // nothing to try here // mess with protected access issue - these all work because in the same package Account cantgetto = new Account("2345",100.00); System.out.println("cantgetto " + cantgetto); System.out.println("PIN: " + cantgetto.PIN); // only can get to since in the same package Savings cangetto = new Savings("3456", 200.00); System.out.println("cangetto " + cangetto); System.out.println("PIN: " + cangetto.PIN); System.exit(0); } }