I know I'm not writing the code correctly to bring over my withdrawal and deposit methods from my Account Class can someone please help me.
Ok, let�s take a look at this issue. You appear to be confusing overriding of constructors and methods.
An important point to understand is that while Subclasses do automatically inherit methods, they do not automatically inherit constructors. Let�s make a couple of simple classes to demonstrate this point.
So we have the Class Baby which is a Subclass of Human. Notice that the Baby only overrides the method sayHello() from Human and it does not declare any constructors. Now let�s make a little class to use these classes:
This will compile and run, giving us the output:
ONE:
name: John Doe
ah-hem
Hello, my name is John Doe.
TWO:
name: John Doe
ah-hem
Wahhhh!
Notice that the instance of Baby (�two�) called Baby�s sayHello method since it was overridden, but still calls Human�s getName() and cough() methods. Therefore, we are able to override methods when we need to, or use the superclass� methods if desired.
Now let�s look at the constructors. We declared a no-parameter constructor in the class Human:
Public Human()
But we did not do so for Baby. So you might be thinking that when we call the constructor Baby() in this line of code:
Human two = new Baby();
That we are actually calling the Human() constructor � well, we are, but not
directly � if no constructor is specified, as is the case of our Baby class, the object will have a default no-parameter constructor. Therefore, even though we didn�t type it in our class, Baby has a constructor of:
Public Baby() { }
That is what is called by TestClass in the line:
Human two = new Baby();
Ok, so the question then becomes how did two, the instance of baby, get the name �John Doe� when that is only defined in the class Human? The answer is that when you invoke a constructor, all the constructor�s of its superclasses are called first. So, even when we created �one�, with this line:
Human one = new Human();
The JVM actually first called the constructor Object() (since all classes implicitly extend Object) and then processed through the Human constructor code, in this case assigning the value �John Doe� to the attribute name. So when the JVM runs this line:
Human two = new Baby();
The chain of events is:
The default constructor Baby() is called The constructor Baby() immediately calls its super constructor Human() The constructor Human() immediately calls its super constructor Object() The Object() constructor runs, then execution returns to the constructor Human() The constructor Human() runs its code, which assigns the value �John Doe� to the attribute name. Execution returns to the Baby() constructor, which has no code of its own. The created object is assigned to the reference two. It is for this reason that if explicitly stated, super() (or any super call like super(�string�), super(1, 2, 2.0), etc) must be the first statement in a constructor. But even if it is not explicitly stated, the no-parameter constructor of the super class is called. Let�s take a look at this by changing our classes a little:
Notice these changes:
We added output strings to all the constructors to show which constructors are called.We added two constructors to the Baby class, but notice that the Baby(String name) constructor does not assign the received name to the name attribute. (This is done in order to illustrate a point).We�ve changed our TestClass to use the constructors that take names. Now when we run the TestClass, we get the following output:
Creating 'one'
Constructor Human(String name) called
Creating 'two'
Constructor Human() called
Constructor Baby(String name) called
ONE:
name: Fred
ah-hem
Hello, my name is Fred.
TWO:
name: John Doe
ah-hem
Wahhhh!
Notice that even though we used the constructor Baby(String name) it called the super constructor Human() and not Human(String name). This is due to the fact that we did not explicitly tell it to do so, and therefore the implicit call to super() was made. � and notice that since out Baby(String name) constructor did not assign the name parameter to the name attribute, out Baby object end up with the Human() constructor default name. If we changed the Baby class to have this constructor:
Our Baby object would get assigned the name passed by the call:
Human two = new Baby("Pebbles");
We could also do this:
This would have the same end result, but the chain of events would be that the name attribute would be assigned the value of �John Doe� (when the implicit call to super() is executed) and then the attribute would be assigned the name �Pebbles� by the this.name = name; line of code.
Ok, hopefully all that discussion makes things a little clearer for you. So let�s take a look at your SavingsAccount code:
The first issue is that you have two constructors (on lines 17 & 22) with the save signature, namely:
public SavingsAccount(double double)
You cannot have two constructors with the same signature in a class. Nevertheless, when you look at things, these are not what you wanted. In your super call, you are passing the undeclared variables
withdraw and
deposit. Give that some logical thought, and compare it to the real world. When you make a deposit or a withdraw, do you want to create a new SavingsAccount object? Does the bank open a new account every time you make a withdraw or a deposit? No. So that�s probably not what you want to do. So just delete those constructors completely.
Instead, your SavingsAccount must simply make the withdraw or deposit, just as your Account class did, using
methods. In the case of the Deposit, nothing is going to be different in your SavingsAccount, so do you even need to override that method in your SavigsAccount class? Look at the Baby class above. Since it coughs the same as a Human, it didn�t override the cough method. But we can still call the method on a baby object by saying:
So your SavingsAccount already has a working and viable deposit method (which it automatically inherits from its superclass Account) so you do not have to rewrite it or write any more code (welcome to the glorious would of Object Oriented Programming and
Polymorphism!!!)
The withdraw method on the other hand is a different story. Here you must have code to handle the possibility of an overdrawn account; so you will want to override the withdraw class in your SavingsAccount class. Now, this is where you were probably getting confused with the call to super.
Going back to our Baby example, let�s say I did want to override the cough method, so that the Baby does something completely different. I could simply do this:
This would completely replace anything the Human class does. However, lets say I wanted the Baby.cough() method to do everything the Human.cough() method does, but also something else; I could do this:
Now my Baby.cough() method does everything the Human.cough() method does, and then some. This saves me rewriting the cough() code from Human in my Baby class, saving extra coding. Granted in this little example that is all of one line of code, but in a real world example, it may be dozens and dozens of lines of code. But even with only one line of code, it makes sense anyway. If I want to change how a human coughs, from �ah-hem� to �ahhh-hemm!� � I can change it in just one place, and all subclasses change with it, so my Baby class will automatically change from �ah-hem giggle� to �ahhh-hemm! giggle� without needing to recode the Baby class.
Give these ideas some thought and decide how to implement your SavingsAcount.withdraw(double) method. You could:
call the super.withdraw(double), test the balance, and then if it causes an overdrawn account, recall the super method with the negative withdraw amount (to return the balance back to the pre-transaction amount) and then throw an OverDrawnException (a class you could write by extending (subclassing) the Exception class) or otherwise signal an overdrawn account.Test if balance - amount will be less then zero. If so, throw the Exception; if not make the withdraw. other ideas... The point being, you need to override the withdraw method and not do it through an alternative constructor. Give a try at reworking your SavingsAccount methods with that in mind. If you are still having problems, post a reply and I or someone else can help you out further.
There is one other place where you have an issue.
Take a look at this line in your TestSavingsAccount class:
Now take a look at the constructors in your SavingsAccount class (after you delete the two erroneous ones I mentioned above)
Do you notice an issue? My discussion above on constructors and their lack of �automatically� being implemented should point out the problem. Look at the signature of the constructor your TestSavingsAccount calls, and the signatures of the constructors available in your SavingsAccount class.
I hope this all helps you out. If not, I just did
a lot of tying for nothing - lol