Section 1: Polymorphism Example
- Suppose a set of account classes such as
CheckingAccountandSavingsAccountare derived from superclassAccount. - In object-oriented programming, each of these classes might be endowed with the
ability to
closeMonth(). - Although each class has its own
closeMonth()method, thecloseMonth()method for each account is quite different. - When performing end-of-month tasks, whatever the account may be,
it would be nice to be able to treat all of the accounts generically as objects of the superclass
Account. - Then to perform any monthly account tasks, we could simply call method
closeMonth()of superclassAccountand let the program determine dynamically (that is, at execution time) which subclasscloseMonth()method to use. - To enable this kind of behavior, we declare
closeMonth()in the superclass, and then we overridecloseMonth()in each of the subclasses to handle end of month. - In the subclass
CheckingAccount, thecloseMonth()method would levy a charge of $25 for any overdrawn accounts, or a charge of $4 for any account whose balance has dropped below $2500. - In the subclass
SavingsAccount, thecloseMonth()method levy a charge of $35 for any overdrawn accounts, or otherwise calculate interest earned. - Each close of month activity, however, is initiated by a call to the
closeMonth()method associated with the superclassAccount, and the proper action is determined dynamically, depending on the type of account. - To test this behavior, we declare an array that holds an object of type
CheckingAccountand an object of typeSavingsAccount. - Then we direct each array item to
closeMonth(), and the end-of-month calculations are performed correctly, based on the type of account.
// Account class - the base class
class Account {
#balance;
constructor(startBalance) {
this.#balance = startBalance;
}
set balance(value) {
this.#balance = value;
}
get balance() {
return this.#balance;
}
closeMonth() {}
}
// derived class CheckingAccount - overrides closeMonth method to handle checking fees
class CheckingAccount extends Account {
// This overrides the base class method.
closeMonth() {
if (super.balance < 0) {
// If balance is negative, apply a $25 charge
super.balance = super.balance() - 25;
}
else if (super.balance < 2500) {
// If balance is less than 2500, then apply monthly charge
super.balance = (super.balance - 4);
}
}
}
// derived class SavingsAccount - overrides closeMonth method to handle savings fees
class SavingsAccount extends Account {
get interest() {
return this.#interestRate;
}
set interest(value) {
this.#interestRate = value;
}
// This overrides the base class method.
closeMonth() {
if (super.balance < 0) {
// If balance is negative, apply a $35 charge
super.balance = super.balance() - 35;
}
else {
// apply an interest equal to that stored in the interestRate variable
super.balance = (super.balance * (1 + this.#interestRate));
}
}
}
function test() {
let acct1 = new CheckingAccount();
acct1.balance = 1200;
alert("The checking balance for acct1 is initially " + acct1.balance);
acct1.closeMonth();
alert("The end-of-month checking balance for acct1 is " + acct1.balance);
let acct2 = new SavingsAccount(7600);
alert("The savings balance for acct2 is initially " + acct2.balance);
acct2.closeMonth();
alert("The end-of-month savings balance for acct2 is " + acct2.balance);
alert("*** Moving to array of objects ***");
let acctList = [acct1, acct2];
acctList[0].closeMonth();
alert("The end-of-month " + getType(acctList[0]) + " balance for acctList[0] is " + acctList[0].balance);
acctList[1].closeMonth();
alert("The end-of-month " + getType(acctList[1]) + " balance for acctList[1] is " + acctList[1].balance);
}
function getType(clsObject) {
var acctType;
if (clsObject instanceof CheckingAccount) {
acctType = "checking";
}
else {
acctType = "savings";
}
return acctType
}