Link to home
Start Free TrialLog in
Avatar of c18drm
c18drm

asked on

Anyone help with building a bank using abstract class

I'm almost there but noone seems to answer in my other question post.
This is my driver class, its throwing up a few errors, mainly imcompatible types but also stating that the variable account is not found in class AccountWork.




package Assignment3;

import java.io.*;
import java.text.*;
import java.util.*;

public class AccountWork {

  public static Branch acc = new Branch();
  static PrintWriter screen = new PrintWriter(System.out, true);
  static BufferedReader keyboard = new
  BufferedReader ( new InputStreamReader (System.in));

  public static void main (String[] args) throws IOException{
    CurrentAccount ca = new CurrentAccount(1234,500 );
    CreditAccount cr = new CreditAccount(5678, 400);
    runMenu(acc);
    acc.add(ca);
    acc.add(cr);
    }

  static void runMenu(Branch acc){
    final int QUIT = 6;
    int choice;
    do{
      displayMenu();
      choice = getChoice();
      executeChoice(choice, acc);
    } while (choice != QUIT);
  }

  static int getInteger(){
    try{
        return(Integer.parseInt((keyboard.readLine()).trim()));
    }
    catch (Exception e){
      return 0;
    }
  }

    static double getDouble(){
    try{
        return(Double.parseDouble((keyboard.readLine()).trim()));
    }
    catch (Exception e){
      return 0;
    }
  }

  static void displayMenu(){
    screen.println(" 1. Create new account");
    screen.println("2. Deposit to an account");
    screen.println("3. Withdraw from an account");
    screen.println("4. Transfer between accounts");
    screen.println("5. Cash available");
    screen.println("6. Quit");
  }

  static int getChoice(){
    int choice;
    screen.print("Enter your choice   ");
    screen.flush();
    choice = getInteger();
    return choice;
  }


  static void executeChoice(int choice, Branch acc){
    switch (choice){
    case 1: addAccount (acc);
      break;
    case 2: depositToAccount(acc);
      break;
    case 3: withdrawFromAccount(acc);
      break;
    case 4: transferTo(acc);
      break;
    case 5: displayCash(acc);
      break;
     }
     }


  static void addAccount(Branch acc){
    Account account;
    int accId, accType;
    double money;
    screen.println("What type of account? 1. Current 2. Credit ");
    accType = getInteger();
    screen.print("What is the new account ID? ");
    accId = getInteger();
    screen.print ("How much money will be in the account? ");
    money = getDouble();
      if (accType == 1){
      account = new CurrentAccount(accId, money);
      acc.add(account);
      }
      else if (accType == 2){
      account = new CreditAccount(accId, money);
      acc.add(account);
      }
  }




  static void depositToAccount(Branch acc){
    int accId;
    double money;
    screen.println("Please enter the account ID to deposit to? ");
    screen.flush();
    accId = getInteger();
    Account account= acc.getAccountByName(accId);
      if(account instanceof  CurrentAccount)
      {
      CurrentAccount cAccount = (CurrentAccount) account;
      screen.println("How much would you like to deposit? ");
      screen.flush();
      money = getDouble();
      account = cAccount.deposit(money);
      }
    }

    static void withdrawFromAccount(Branch acc){
      int accId;
      double money;
      screen.println("Please enter the account ID to withdraw from? ");
      screen.flush();
      accId = getInteger();
      Account account = acc.getAccountByName(accId);
        if (account instanceof CurrentAccount)
        {
        CurrentAccount cAccount = (CurrentAccount) account;
        screen.println("How much would you like to withdraw? ");
        screen.flush();
        money = getDouble();
        account = cAccount.withdraw(money);
        }
        else if (account instanceof CreditAccount)
        {
        CreditAccount crAccount = (CreditAccount) account;
        screen.println("How much would you like to withdraw? ");
        screen.flush();
        money = getInteger();
        account = crAccount.withdraw(money);
        }
    }


    static void displayCash(Branch acc){
      int accId;
      screen.println("Please enter the account ID you wish to display?  ");
      screen.flush();
      accId = getInteger();
      Account account = acc.getAccountByName(accId);
        if (account instanceof CurrentAccount)
        {
        CurrentAccount cAccount = (CurrentAccount) account;
        Account  =  cAccount.getBalance();
        screen.println(account);
        }
    }


    static void transferTo(Branch acc){
      int accId;
      double money;
      screen.println("Please enter the account to transfer from ?");
      screen.flush();
      accId = getInteger();
      Account account = acc.getAccountByName(accId);
        if (account instanceof CurrentAccount)
        {
        CurrentAccount cAccount = (CurrentAccount) account;
        screen.println("How much to transfer? ");
        screen.flush();
        money = getInteger();
        screen.println("What account to tranfer to? ");
        accId = getInteger();
        Account = cAccount.transferTo(accId, money);
        }
      }




}
Avatar of zzynx
zzynx
Flag of Belgium image

>> stating that the variable account is not found in class AccountWork.
At what line exactly in this bunch of code ;°)
Avatar of c18drm
c18drm

ASKER

several.
in the displayCash method it gives that error
>> Account = cAccount.transferTo(accId, money);
should be with small a I guess
Just some remarks:

>> static void depositToAccount(Branch acc){     // rather strange (and making it unreadable) to call a Branch "acc"

>> Account account= acc.getAccountByName(accId);   // rather strange to pass in integer to a function called "getAccountByName"
Avatar of c18drm

ASKER

k, so once i change them all to a small A, I#m getting lots of incompatibilty error messages.
all saying they require something from my account class, whereas its found boolean, void, double etc.
Come on please help all you experts out there!!!
Avatar of c18drm

ASKER

ok so change getAccountByName to getAccountByIdentifier.
as for the Branch acc, there is essentially no different branches anyway, the Branch class simply holds a collection of the accounts in a vector
>> k, so once i change them all to a small A,
*all* ???

"Account" is the name of your class
"account" is the name of your variable
Avatar of c18drm

ASKER

I know, I've only changed the parts that I *think* need to be changed
static methods should be used sparingly in Java, otherwise you end up by writing procedural code, which in addition to being generally undesirable, partially defeats the object of Java itself
In Branch getAccountByName() is defined as taking an Integer object as parameter.

Here
>>int accId = getInteger();
>>  Account account = acc.getAccountByName(accId);
you pass an int.
That's NOT the same.


Moreover:

  public void add (Account account){
    accounts.add(account);                           // <<<<< apparently you're collecting Account objects in the Vector "accounts"
  }

Then this looks very strange:

  public Account getAccountByName(Integer accountId){
    int index = accounts.indexOf( accountId); // <<<<<<<<<<< passing an Integer while the objects in the Vector are Account objecs ?????
    return (Account) accounts.get(index);
  }

I think it should be:

...Errrr. Don't know.
How does your Branch class looks like, now?
Avatar of c18drm

ASKER

my branch class is:

class Branch{
  private Vector accounts;
  public Branch(){
    accounts = new Vector();
  }

  public void add (Account account){
    accounts.add(account);
  }

  public void displayAccounts(PrintWriter p){
    for(int n=0; n<accounts.size(); n++)
      p.println(accounts.get(n)) ;
  }

  public Account getAccountByName(int accountId){
    int index = accounts.indexOf(accounts,  accountId);
    return (Account) accounts.get(index);
  }


  }
Avatar of c18drm

ASKER

To be honest I'm not 100% sure that my branch class is doing everything its supposed to be
It certainly is more OO, but getAccountByName doesn't seem to be doing what it says it will ...
Avatar of c18drm

ASKER

so...any suggestions?
This is actually what an expert on here advised me to use for this method.
As I said I'll change the name of the method to getAccountByIdentifier which will be the account ID
getAccountById would be OK
indexOf() should be used to find the index (in accoutns) of a given Account object

something like:

public int getIndex(Account account){
    return accounts.indexOf(account);
}

you seem to need a function like

public Account get(int index) {
   if (index < accounts.size())
      return (Account)accounts.get(index);
   else
      return null;
}
Just for completeness, may as well post Account too
...while getAccountById() should more look like:

public Account getAccountById(int id) {

    Iterator it = accounts.iterator();
    while (it.hasNext()) {
         Account acc = (Account)it.next();
         if (acc.getId()==id)
             return acc;
    }
    return null; // not found
}
Avatar of c18drm

ASKER

ok, here's the abstract class Account:

import java.util.*;
import java.io.*;

abstract class Account {
  protected int id;
  protected double balance;

  public Account(int id, double balance) {
    this.id = id;
    this.balance = balance;
  }


  public int getId(){
    return this.id;
  }

  public double getBalance(){
    return balance;
  }

  public void deposit( double money){
    balance += money;
  }

  public boolean transferTo( Account somebody, double money){
    if (money>0){
      if (withdraw(money)){
        somebody.deposit(money);
        return true;
      }
    }
    return false;
  }


  public boolean equals(Object obj)
{
 if(obj instanceof java.lang.Integer)
 {
   Integer accountName = (Integer) obj;
   return (id == accountName.intValue());
 }
 else if (obj instanceof Account)
{
   Account compared = (Account) obj;
   return  (id == compared.getId());
}
  return false;
}



  abstract public boolean withdraw(double money);
  abstract public double availableCash();
}





class CreditAccount extends Account{
  public CreditAccount(int id, double balance){
    super (id, balance);
  }
  public boolean withdraw (double money){
    if (balance - money >=0){
      balance -= money;
      return true;
    }
    else return false;
  }
  public double availableCash(){
    return balance;
  }
}




class CurrentAccount extends Account{
  private double limit = -250;
  public CurrentAccount (int id, double balance){
    super(id, balance);
  }
  public boolean withdraw(double money){
    if (balance-money >= limit){
      balance -= money;
      return true;
    }
    else return false;
  }
  public double availableCash(){
    return (balance - limit);
  }
}

The above iterates through all the Account objects and searches for the one having the given id
>> The above
I refer to my comment here
Another one:

the withdraw() functions return a boolean

Then why do you write

>> account = cAccount.withdraw(money);

account being an Account object?
public Account getAccountById(int id) {
      int ix = accounts.indexOf(new Account(id))
      return ix >= 0? (Account)accounts.get(ix) : null;
}

Account.equals looks odd - can you explain?
... and since deposit() doesn't return anything (void) you shouldn't write

>> account = cAccount.deposit(money);
>>int ix = accounts.indexOf(new Account(id))

(or, per your definition)

int ix = accounts.indexOf(new Account(id), 0.0)


In displayCash() replace

>>        Account  =  cAccount.getBalance();
>>        screen.println(account);

simply by

screen.println( cAccount.getBalance());
Avatar of c18drm

ASKER

>>>the withdraw() functions return a boolean

Then why do you write

>> account = cAccount.withdraw(money);

account being an Account object?



This is where all my problems are cominf from when I try to compile.
how should this be written, should I change the withdraw method or the part in the driver?
And the last one:

Don't write

       >>account = cAccount.transferTo(accId, money);

since it returns a boolean
There doesn't seem to be a good reason for withdraw and deposit being anything other than void
>> how should this be written, should I change the withdraw method or the part in the driver?

*You* should decide!
withdraw() looks OK.
It seems like it return true if there was enough money on the account and false if there isn't.
So you could write something like:

boolean success =  cAccount.withdraw(money);
if (success)
    screen.println("Withdraw successful");
else
    screen.println("Withdraw unsuccessful: not enough money on the account!");
 
Avatar of c18drm

ASKER

I'd set the withdraw and deposit's to be boolean so that
a/  the credit account can't be overdrawn
b/  the current account does not go below -250

thought this would be the best way to do it?
>> There doesn't seem to be a good reason for withdraw and deposit being anything other than void
Not for deposit(), but there IS for withdraw() (cf. above)
>>Not for deposit(), but there IS for withdraw() (cf. above)

Yes that's OK if you need to check
>> I'd set the withdraw and deposit's to be boolean so that
>> a/  the credit account can't be overdrawn
>> b/  the current account does not go below -250

You can prevent these things happening apart from whatever type these functions return.
But if the caller of this functions is interested in the fact that those special cases have happened (e.g. going below -250 is avoided)
you have to return something to indicate that. In that case a boolean is OK. (see my previous example)
Avatar of c18drm

ASKER

ok I'm getting there.
look guys, your help is so much appreciated, starting to make a little more sense now
Avatar of c18drm

ASKER

the only part I can't get sorted now is the transferTo method.
Because I'm going to be reading in an int which will be the account number, the method in the Account class is expecting an Account object (that's how I'm interpreting it anyway)
in transferTo()

you should replace

>> cAccount.transferTo(account, money);
by

   cAccount.transferTo(acc.getAccountById(accId), money);

to make it work ;°)
...and since the type of the Account doesn't matter (since transferTo() is defined on Account)

you can rewrite it as:

    static void transferTo(Branch acc){
      screen.println("Please enter the account to transfer from ?");
      screen.flush();
      int accIdFrom = getInteger();
      screen.println("How much to transfer? ");
      screen.flush();
      double money = getInteger();
      screen.println("What account to tranfer to? ");
      int accIdTo = getInteger();
      acc.getAccountById(accIdFrom).transferTo(acc.getAccountById(accIdTo), money);
    }
and replace

    double money = getInteger();
by
    double money = getDouble();

;°)
Mmmm. I think you should be fine now...
Offline I go. CU.
Since you want to grab the account based on it's account ID you'd better use this as Branch class:

import java.util.*;
import java.io.*;

class Branch {
    private Map accounts = new HashMap();       // Better use a map. Key=account ID (as Integer), value=the account
   
    public Branch() {
    }

    public void add (Account account){
        accounts.put(new Integer(account.getId()), account);
    }
   
    public void displayAccounts(PrintWriter p){
        Iterator it = accounts.keySet().iterator();
        while (it.hasNext()) {
            Integer key = (Integer)it.next();
            p.println(accounts.get(key).toString());
        }
    }

    public Account getAccountById(int id) {
        Integer key = new Integer(id);
        if ( !accounts.containsKey(key) )
            return null;
        return (Account) accounts.get(key);
    }
}
For the above to compile and work in the class Account I added a function toString():

  public String toString() {
      return ("Account id: " + getId() + " - Balance: " + getBalance());
  }


Another thing you should probably make safer is the entering of the account ID.
Now you use getInteger() for that.
But what if they enter an Id for which no account exists?

Instead of getInteger() use getAccountId().
Same for the account type (only 1 or 2 are valid).

/*
 * AccountWork.java
 *
 */

package Assignment3;

import java.io.*;
import java.text.*;
import java.util.*;

public class AccountWork {

  private static Branch acc = new Branch();
  private static PrintWriter screen = new PrintWriter(System.out, true);
  private static BufferedReader keyboard =
    new BufferedReader ( new InputStreamReader (System.in));

  public static void main (String[] args) throws IOException{
    CurrentAccount ca = new CurrentAccount(1234, 500);
    CreditAccount cr = new CreditAccount(5678, 400);
    AccountWork myApp = new AccountWork();
    acc.add(ca);
    acc.add(cr);
    acc.displayAccounts(screen);
    myApp.runMenu(acc);
  }

  private void runMenu(Branch acc){
    final int QUIT = 6;
    int choice;
    do{
      displayMenu();
      choice = getChoice();
      executeChoice(choice, acc);
    } while (choice != QUIT);
  }

  private int getInteger(){
    try{
        return(Integer.parseInt((keyboard.readLine()).trim()));
    }
    catch (Exception e){
      return 0;
    }
  }

    private double getDouble(){
    try{
        return(Double.parseDouble((keyboard.readLine()).trim()));
    }
    catch (Exception e){
      return 0;
    }
  }

  private void displayMenu(){
    screen.println("=================================");
    screen.println("1. Create new account");
    screen.println("2. Deposit to an account");
    screen.println("3. Withdraw from an account");
    screen.println("4. Transfer between accounts");
    screen.println("5. Cash available");
    screen.println("6. Quit");
    screen.println("=================================");
  }

  private int getChoice(){
    int choice;
    screen.print("Enter your choice   ");
    screen.flush();
    choice = getInteger();
    return choice;
  }


  private void executeChoice(int choice, Branch acc){
    switch (choice){
        case 1: addAccount (acc);
          break;
        case 2: depositToAccount(acc);
          break;
        case 3: withdrawFromAccount(acc);
          break;
        case 4: transferTo(acc);
          break;
        case 5: displayCash(acc);
          break;
        case 6:
            screen.println("Bye");
            screen.flush();
          break;
     }
  }


  private void addAccount(Branch acc){
    Account account;
    int accId, accType;
    double money;
    screen.println("What type of account? 1. Current 2. Credit ");
    accType = getAccountType();
    screen.println("What is the new account ID? ");
    accId = getAccountId(acc);
    screen.println("How much money will be in the account? ");
    money = getDouble();
    if (accType == 1){
      account = new CurrentAccount(accId, money);
      acc.add(account);
    }
    else if (accType == 2){
      account = new CreditAccount(accId, money);
      acc.add(account);
    }
  }

  private void depositToAccount(Branch acc){
    screen.println("Please enter the account ID to deposit to? ");
    int accId = getAccountId(acc);
    Account account= acc.getAccountById(accId);
    screen.println("How much would you like to deposit? ");
    double money = getDouble();
    account.deposit(money);
    screen.println("Available cash: " + account.availableCash());
  }

    private void withdrawFromAccount(Branch acc){
      int accId;
      double money;
      screen.println("Please enter the account ID to withdraw from? ");
      screen.flush();
      accId = getAccountId(acc);
      Account account = acc.getAccountById(accId);
      screen.println("How much would you like to withdraw? ");

      money = getDouble();
      if ( !account.withdraw(money) ) {
        screen.println("Withdraw unsuccessful. Not enough available: " + account.availableCash());
      }
      else
          screen.println("Withdraw successful. Available cash: " + account.availableCash());
      screen.flush();
    }


    private void displayCash(Branch acc){
      int accId;
      screen.println("Please enter the account ID you wish to display?  ");
      accId = getAccountId(acc);
      Account account = acc.getAccountById(accId);
      screen.println("Available cash: " + account.availableCash());
      screen.flush();
    }

    private void transferTo(Branch acc){
      screen.println("Please enter the account to transfer from ?");
      screen.flush();
      int accIdFrom = getAccountId(acc);
      screen.println("How much to transfer? ");
      screen.flush();
      double money = getDouble();
      screen.println("What account to tranfer to? ");
      int accIdTo = getAccountId(acc);
      if ( acc.getAccountById(accIdFrom).transferTo(acc.getAccountById(accIdTo), money) ) {
          screen.println("Transfer successful. Available cash: " + acc.getAccountById(accIdTo).availableCash());
      }
      screen.flush();
    }
   
    private int getAccountId(Branch accounts) {
        boolean valid = false;
        int id = 0;
        do {
            id = getInteger();
            valid = (accounts.getAccountById(id)!=null);
            if (!valid)
                screen.println("No account available with this id... Try again.");
        } while (!valid);
        return id;
    }

    private int getAccountType() {
        boolean valid = false;
        int type = 0;
        do {
            type = getInteger();
            valid = (type==1 || type==2);
            if (!valid)
                screen.println("Invalid type... Try again.");
        } while (!valid);
        return type;
    }
   
}
Avatar of c18drm

ASKER

Hi, thanks again for your hints and tips.
I'm not looking to use a hash-table for this, unfortunatelt, so going to stick with the vector, will the same principles apply?
Avatar of c18drm

ASKER

forget the last comment, got working now, just cosmetics to fix.
will come on later and distribute points.
but thanks so much!!!!
Avatar of c18drm

ASKER

if anyone is online, where would I add in to save the accounts to a txt file??
i mean in what part of the coding
ASKER CERTIFIED SOLUTION
Avatar of zzynx
zzynx
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>> save the accounts to a txt file.
I would go for serialization of the Branch object
Serializing an Object: http://javaalmanac.com/egs/java.io/SerializeObj.html
Deserializing an Object:http://javaalmanac.com/egs/java.io/DeserializeObj.html
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Easier? imho, merely a matter of taste ;°)
I find it easier ;-) With the advantage of the file being human-readable. File size it slightly bigger that ObjectOutputStream though
Proposal: split zzynx-CEHJ