I somehow need to check the value of a variable amount being received in the subclass before sending it to the superclass.
This is what I have for my superclass
//superclass
public class Account
{
private double balance;
public Account( double amount )
{
balance = amount;
}
public Account()
{
this(0.0);
}
public void deposit( double amount )
{
balance += amount;
}
public void withdraw( double amount )
{
balance -= amount;
}
public double getBalance()
{
return balance;
}
}
This is what I have for my subclass
public class SafeAccount extends Account
{
public SafeAccount(double amount)
{
// something to check if amount is positive before sending it to
super
// if it's not positive, use no argument constructor to set balance ==
0.0
}
}
I think I am supposed to use "this(amount)" to somehow check it, but I'm not exactly sure how that will work.
super() must be the first statement in a constructor body so you cannot perform checks before it.
Simple work around:
public class SafeAccount extends Account
{
public SafeAccount(double amount)
{
super(Math.max(0.0, amount));
}
}
If you really must use the no arg constructor a more complex work around would be:
public class Account {
Account() {
}
Account(double x) {
}
}
public class SafeAccount extends Account {
private SafeAccount() {
}
private SafeAccount(double amount) {
super(amount);
}
public static SafeAccount boo(double x) {
if (x < 0.0) {
return new SafeAccount();
}
return new SafeAccount(x);
}
}
Use private constructors in your subclass to prevent instantion from constructor and supply a factory method that does the checks you want.
You can use following statement
class SafeAccount extends Account {
public SafeAccount(int balance) {
super(balance > 0? balance: 0);
}
}
But in general such Inheritance hierarchy needs to be rechecked for correctness of design.
Related
This is only the second time I use this, and the first time I got really good help so I am hoping I could get some more help!
Background:
My program tests my Account class by creating an object that holds a balance and other things. The instructions say I need to override the subclasse's "Withdraw" and "Deposit" methods in order to keep track of a transaction.
I did this, but it doesn't use the current balance and instead just sends in a 0. I want to be able to keep the new balance so it actually withdraws or deposits from the current balance.
Sorry if this makes no sense, if any clarification is needed I will try to explain in a different way.
Below is my code snippet:
Note: I kept out the stuff that already works (constructors and other methods) that has nothing to do with this:
Account.java
public class Account
{
private static double balance;
public void Withdraw(double withdrawAmount)
{
this.balance -= withdrawAmount;
}
public void Deposit(double depositAmount)
{
this.balance += depositAmount;
}
}
UserAccount.java
public class UserAccount extends Account
{
private ArrayList<Transactions> transactions = new ArrayList();
#Override
public void Withdraw(double withdrawAmount)
{
super.Withdraw(withdrawAmount);
Transactions thisTransaction = new Transactions('W',
withdrawAmount, this.AccBalance(), "Withdraw");
this.transactions.add(thisTransaction);
}
#Override
public void Deposit(double depositAmount)
{
super.Deposit(depositAmount);
Transactions thisTransaction = new Transactions('D',
depositAmount, this.AccBalance(), "Deposit");
this.transactions.add(thisTransaction);
}
public void fillTransactions(char type, double amount, double balance)
{
switch (type) {
case 'D':
this.Deposit(amount);
break;
case 'W':
this.Withdraw(amount);
break;
default:
System.out.println("ERROR fillTransactions");
break;
}
}
public static void main(String[] args) {
ArrayList<Transactions> copyTransactions;
UserAccount thisAccount = new UserAccount("George", 1122, 1000);
thisAccount.MutAIR(.015);
thisAccount.fillTransactions('D', 30, thisAccount.AccBalance());
thisAccount.fillTransactions('D', 40, thisAccount.AccBalance());
thisAccount.fillTransactions('D', 50, thisAccount.AccBalance());
thisAccount.fillTransactions('W', 5, thisAccount.AccBalance());
thisAccount.fillTransactions('W', 4, thisAccount.AccBalance());
thisAccount.fillTransactions('W', 2, thisAccount.AccBalance());
}
The Transactions class that I have holds the type (withdraw or deposit), the amount getting withdrawn or deposited, and the balance. What happening is when I call the super class from the overridden deposit or withdraw methods, it sets balance to 0 so it says that the balance is 50, or 40, or -5 when I want the original balance with the deposited or withdrawn currency.
If anyone could help, that would be amazing! I can clarify if anything is confusing! Thank you!
Hey I think you are not setting the balance in the constructor of UserAccount. Here's an example of setting variable
Assume class A as Account and class B as UserAccount
class A {
private double balance;// Don't use static
public A(double balance) {// You will need this
this.balance = balance;
}
public double getBalance() { return balance; }
}
class B extends A {
public B(double balance) {
super(balance);//Important
}
public void d() { System.out.println(getBalance()); }
}
public class Main {
public static void main(String args[]) {
B b = new B(100.0);
b.d();
}
}
If you use static balance in the super class, then only one instance of it will be used for all the objects, since you want individual balance for each UserAccount I guess.
Please consider two classes :
Data Definition Class :
public class A {
private int amount = 1000;
public A(int amount){
this.amount = amount
}
public int getAmount(){
return amount ;
}
}
Main Class :
public class B {
public static void main (String arg[]){
A a = new A(2000);
System.out.println("Amount:"+a.getAmount());
}
}
Since I am passing 2000 to the constructor, I am getting 2000 in the output. But I would like to keep a option of if the user doesn't specifiy any amount, it should print
the default value which is 1000 as mentioned in the private variable in data definition class.
Is there a way I can accomplish my task using the constructor?
public class A {
private int amount;
public A() {
amount = 1000;
}
public A(int amount) {
this.amount = amount;
}
public int getAmount() {
return amount;
}
}
You just need to create an empty constructor
public A(){
}
And in your main you will be able to do this:
A a = new A();
You can provide default constructor along with the one argument constructor you mentioned. This way user don't have to pass the amount if he don't want to while creating the object.
Create an empty constructor
public class A {
private int amount = 1000;
public A(){
}
public A(int amount){
this.amount = amount;
}
public int getAmount(){
return this.amount;
}
}
I am writing a code that create an array of instances of Account object in another class (Bank).
I am initializing the array inside the main method, but it is not accessible inside the Bank class.
What I want to do is create 4 instances of the Account class and to be able to perform all tasks inside the Bank class methods. Is there a way that I can do this?
this is my code
Account.java
package question1;
import java.util.Date;
public class Account {
public int AccountNum;
public double BALANCE;
public Date OPENDATE;
public String OwnerName;
public Account() {
// TODO Auto-generated constructor stub
}
public Account(int accnum, double balance, Date opendate, String ownername) {
this.AccountNum = accnum;
this.BALANCE = balance;
this.OPENDATE = opendate;
this.OwnerName = ownername;
}
public int getAccountNum() {
return AccountNum;
}
public void setAccountNum(int accountNum) {
AccountNum = accountNum;
}
public double getBALANCE() {
return BALANCE;
}
public void setBALANCE(double bALANCE) {
BALANCE = bALANCE;
}
public Date getOPENDATE() {
return OPENDATE;
}
public void setOPENDATE(Date oPENDATE) {
OPENDATE = oPENDATE;
}
public String getOwnerName() {
return OwnerName;
}
public void setOwnerName(String ownerName) {
OwnerName = ownerName;
}
public double yearlyInterest(double balace) {
return balace;
}
}
Bank.java
package question1;
public class Bank {
public static void main(String[] args) {
Account[] acc = new Account[4];
for(int i = 0 ; i<acc.length; i++){
acc[i] = new Account();
System.out.println(acc[i].toString());
}
/// how to continue form here ??
}
}
Call the constructor of the Account class. Now you can set all arguments as desired. Afterwards, you can add the instance to any array or collection.
List<Account> accounts = new ArrayList<Account>(4);
Account myAccount = new Account(123, 100.5, new Date(), "dev leb");
accounts.add(myAccount);
You probably want to have a property of an Account array in your class.
You can set your property in the class body:
public class Bank {
//Set your property here.
private Account[] _acc;
//Initialize in ctor.
public Bank() {
_acc = new Account[4];
}
//....
//You can then use it as a property in your code.
//If needed outside the class, set up setter and getter methods,
//avoiding violating encapsulation.
public Account[] getAcc(){
return _acc;
}
public void setAcc(Account acc){
this._acc = acc;
}
//If you need this to be used inside main, then you must instantiate a
//Bank in main and then make all the appropriate operations there.
public static void main(String[] args) {
Bank bank = new Bank();
Account[] bankAccounts = bank.getAcc();
//....
}
}
My suggestion though is that you use an ArrayList instead:
Set the property:
private List<Account> acc;
And in constructor:
acc = new List();
In order to add an account in a class method:
acc.add(new Account());
In order to retrieve an element by indexing:
acc.get(0);
for more information, look at the ArrayList JavaDoc.
If you are not able to understand why your array that is defined inside the main is not accessible inside your Bank class, then I suggest you search more about Object-Oriented programming, Class definition, instantiation and properties accessibility and manipulation and static methods in Java.
I have created a class by the name of Account. I am then instantiating an object of the type class. All the code is saved in the file TestAccount. But the system gives me an error as shown below
Exception in thread "main" java.lang.ExceptionInInitializerError
at testaccount.TestAccount.main(TestAccount.java:8)
Caused by: java.lang.RuntimeException: Uncompilable source code - class Account is public, should be declared in a file named Account.java
at testaccount.Account.(TestAccount.java:20)
... 1 more
Java Result: 1
Below is my code:
package testaccount;
public class TestAccount
{
public static void main(String[] args)
{
Account Account1=new Account();
Account1.setId(1122);
Account1.setBalance(20000);
Account1.setAnnualInterestRate(4.5);
System.out.println("The monthly interest rate is " + Account1.getMonthlyInterestRate());
System.out.println("The balance after the withdrawal is "+ Account1.withdraw(2000));
System.out.println("The balabce after the deposit is " + Account1.deposit(3000));
}
}
public class Account
{
private int id;
private double balance;
private double annualInterestRate;
private static long dateCreated;
public Account()
{
id=0;
balance=0;
annualInterestRate=0;
dateCreated=System.currentTimeMillis();
}
public Account(int newId,double newBalance)
{
id=newId;
balance=newBalance;
}
public int getId()
{
return id;
}
public void setId(int newId)
{
id=newId;
}
public double getbalance()
{
return balance;
}
public void setBalance(double newBalance)
{
balance=newBalance;
}
public double getAnnualInterestRate()
{
return annualInterestRate;
}
public void setAnnualInterestRate(double newAnnualInterestRate)
{
annualInterestRate=newAnnualInterestRate;
}
public static long getDateCreate()
{
return dateCreated;
}
public double getMonthlyInterestRate()
{
return (annualInterestRate/12);
}
public double withdraw(double newWithdraw)
{
return (balance-newWithdraw);
}
public double deposit(double deposit)
{
return (balance+deposit);
}
}
Can some one tell me what I am doing wrong?
You have to make a new file called Account.java and put your account class in there. this is because when you call account from another class, the jvm will go looking for Account.class and if your account class is in a file named TestAccount.class it wont be able to find it.
Otherwise the compiler wont compile your file
As long as both your classes are in the same package (folder) you don't have to do anything special to "link" the two.
Unless, of course, you want to nest the classes, in which case you put your Account class inside of your TestAccount class. Although I do not recommend this as it is very messy.
It's not a good pratice, and the solutions already present are better but you can move the Account class inside the TestAccount and make it static (put static in front of the class definition). That'll also work.
The abstract method statement (in the super class) must be implemented to return a string representation of a statement.
So I've done the following:
public abstract String statement(); //The abstract method in my super class
..and the method in my subclass:
//#Override
public String statement()
{
return String.format("Account no %d has balance R%d and minimum balance R%d", accountNumber,balance,getMinBalance());
}
My main class just calls the Account class (the super class in question) as follows:
new SavingsAccount(Integer.toString(ao[i]),ao[i+1],ao[a]); //ao being the array which contains the values.
However, the console just terminates without displaying anything (I'm also not familiar with implementation).
Here's the full code:
Main:
public class AccountList
{
public static void main(String[] args)
{
int[] ao = {00000,0,0,12345,500,250,23456,230,-50,34567,340,500,45678,-320,-50,56789,-320,-500};
for(int i=0;i<ao.length;i=i+3)
{
int a = i+2;
if(ao[a]>=0)
{
new SavingsAccount(Integer.toString(ao[i]),ao[i+1],ao[a]);
}
if(ao[a]<=0)
{
new ChequeAccount(Integer.toString(ao[i]),ao[i+1],ao[a]);
}
}
}
}
Super class:
public abstract class Account implements InterestAccount
{
static String accountNumber;
int balance;
public Account()
{
accountNumber = "00000";
balance = 0;
//statement();
}
public Account(String accountNumber,int balance)
{
setAccountNum(accountNumber);
setBalance(balance);
}
public void setAccountNum(String accNum)
{
accountNumber = accNum;
}
public void setBalance(int balance)
{
this.balance = balance;
}
public String getAccountNumber()
{
return accountNumber;
}
public int getBalance()
{
return balance;
}
public abstract String statement();
}
One of the sub-classes:
public class SavingsAccount extends Account
{
int minBalance;
public SavingsAccount()
{
super();
minBalance = 0;
}
public SavingsAccount(String accountNum,int minBalance,int balance)
{
super(accountNum,balance);
setMinBalance(minBalance);
}
public void setMinBalance(int minBalance)
{
this.minBalance = minBalance;
}
public int getMinBalance()
{
return minBalance;
}
#Override
public int calculateInterest(int value) {
if(minBalance>balance)
{
return 0;
}
else
{
return (minBalance*balance)/100;
}
}
//#Override
public String statement()
{
return String.format("Account no %d has balance R%d and minimum balance R%d", accountNumber,balance,getMinBalance());
}
}
You never calls the method statement.
1) create a new SavingsAccount object
new SavingsAccount(Integer.toString(ao[i]),ao[i+1],ao[a]);
2) Constructor class got call by above statement
public SavingsAccount(String accountNum,int minBalance,int balance)
{
super(accountNum,balance);
setMinBalance(minBalance);
}
3) Subclass then call superclass method
public Account(String accountNumber,int balance)
{
setAccountNum(accountNumber);
setBalance(balance);
}
4) SetBalance is called
public void setBalance(int balance)
{
this.balance = balance;
}
5) setMinBalance called
public void setMinBalance(int minBalance)
{
this.minBalance = minBalance;
}
6) End of create object SavingsAccount
No single statement calling the method statement
It might help to know more of your code, but from what I see, there are some possible cases:
Your code runs and terminates without an error. Reason you don't see anything is, there is nothing written to the standard output stream (e.g. via System.out.println()).
Your code has some internal problems, which cause an exception, which again is not shown due to a broken logging mechanism.
In any case, use a debugger to step through you code and determine which parts run perfectly and if any fail. It might help to extract some local variables, give them proper meaningful names and watch their contents during execution.