This commit is contained in:
Nathan Howard 2025-11-29 10:45:30 -08:00
parent c29c430d45
commit 46c70b26f8
24 changed files with 989 additions and 2 deletions

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="/Users/nathanhoward/Documents/Code/OSSU-CS/completedwork/core_programming/02_classbased_design/Jars/tester.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Lab08_Mutation</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=11

View File

@ -0,0 +1,20 @@
// Represents a bank account
public abstract class Account {
int accountNum; // Must be unique
int balance; // Must remain above zero (others Accts have more restrictions)
String name; // Name on the account
public Account(int accountNum, int balance, String name) {
this.accountNum = accountNum;
this.balance = balance;
this.name = name;
}
//EFFECT: Withdraw the given amount
//Return the new balance
abstract int withdraw(int amt);
//EFFECT: Deposit the given funds into this account
//Return the new balance
abstract int deposit(int funds);
}

View File

@ -0,0 +1,33 @@
// Represents a Bank with list of accounts
public class Bank {
String name;
ILoA accounts;
public Bank(String name) {
this.name = name;
// Each bank starts with no accounts
this.accounts = new MtLoA();
}
// EFFECT: Add a new account to this Bank
void add(Account acct) {
this.accounts = new ConsLoA(acct, this.accounts);
}
//EFFECT: Withdraw the given amount
//Return the new balance
public int withdraw(int accountNum, int amt) {
return this.accounts.find(accountNum).withdraw(amt);
}
//EFFECT: Deposit the given funds into this account
//Return the new balance
public int deposit(int accountNum, int funds) {
return this.accounts.find(accountNum).deposit(funds);
}
// EFFECT: Remove the given account from this Bank
public void removeAccount(int accountNum) {
this.accounts = this.accounts.removeAccount(accountNum);
}
}

View File

@ -0,0 +1,24 @@
// Represents a checking account
public class Checking extends Account {
int minimum; // The minimum account balance allowed
public Checking(int accountNum, int balance, String name, int minimum) {
super(accountNum, balance, name);
this.minimum = minimum;
}
@Override
public int withdraw(int amt) {
if (this.balance - this.minimum < amt) {
throw new RuntimeException(amt + " is not available");
} else {
this.balance = this.balance - amt;
return this.balance;
}
}
public int deposit(int funds) {
this.balance = this.balance + funds;
return this.balance;
}
}

View File

@ -0,0 +1,37 @@
// Represents a non-empty List of Accounts...
public class ConsLoA implements ILoA {
Account first;
ILoA rest;
public ConsLoA(Account first, ILoA rest) {
this.first = first;
this.rest = rest;
}
public Account find(int accountNum) {
if (this.first.accountNum == accountNum) {
return this.first;
} else {
return this.rest.find(accountNum);
}
}
public ILoA removeAccount(int accountNum) {
if (this.first.accountNum == accountNum) {
return this.rest;
} else {
return new ConsLoA(this.first, this.rest.removeAccount(accountNum));
}
}
/* Template
* Fields:
* ... this.first ... --- Account
* ... this.rest ... --- ILoA
*
* Methods:
*
* Methods for Fields:
*
*/
}

View File

@ -0,0 +1,29 @@
// Represents a credit line account
public class Credit extends Account {
int creditLine; // Maximum amount accessible
double interest; // The interest rate charged
public Credit(int accountNum, int balance, String name, int creditLine, double interest) {
super(accountNum, balance, name);
this.creditLine = creditLine;
this.interest = interest;
}
public int withdraw(int amt) {
if (this.creditLine < this.balance + amt) {
throw new RuntimeException(amt + " is not available");
} else {
this.balance = this.balance + amt;
return this.balance;
}
}
public int deposit(int funds) {
if (this.balance < funds) {
throw new RuntimeException(
funds + " is greater than line of credit balance: " + this.balance);
}
this.balance = this.balance - funds;
return this.balance;
}
}

View File

@ -0,0 +1,141 @@
import tester.*;
// Bank Account Examples and Tests
public class Examples {
public Examples() {
reset();
}
Bank bank1;
Bank bank2;
Account check1;
Account savings1;
Account credit1;
Account check2;
Account savings2;
Account credit2;
// Initializes accounts to use for testing with effects.
// We place inside reset() so we can "reuse" the accounts
public void reset() {
bank1 = new Bank("First Bank");
bank2 = new Bank("Second Bank");
// Initialize the account examples
check1 = new Checking(1, 100, "First Checking Account", 20);
savings1 = new Savings(4, 200, "First Savings Account", 2.5);
credit1 = new Credit(8, 20, "First Line of Credit", 999, 5.0);
check2 = new Checking(2, 20, "Second Checking Account", 20);
savings2 = new Savings(24, 1000, "Second Savings Account", 2.5);
credit2 = new Credit(28, 0, "Second Line of Credit", 999, 5.0);
bank1.accounts = new ConsLoA(check1, new ConsLoA(savings1, new ConsLoA(credit1, new MtLoA())));
}
// Tests the exceptions we expect to be thrown when
// performing an "illegal" action.
public void testExceptions(Tester t) {
reset();
t.checkException("Test for invalid Checking withdraw",
new RuntimeException("85 is not available"),
this.check1,
"withdraw",
85);
t.checkException("Test for invalid Savings withdraw",
new RuntimeException("1000 is not available"),
this.savings1,
"withdraw",
1000);
t.checkException("Test for invalid Credit withdraw",
new RuntimeException("1000 is not available"),
this.credit1,
"withdraw",
1000);
t.checkException("Test for invalid Credit withdraw",
new RuntimeException("1000 is greater than line of credit balance: 20"),
this.credit1,
"deposit",
1000);
t.checkException("Test for invalid Account number",
new RuntimeException("100 cound not be found"),
this.bank1,
"withdraw",
100,
100);
t.checkException("Test for invalid Account add",
new RuntimeException("100 cound not be found"),
this.bank1,
"removeAccount",
100);
}
// Test the deposit method(s)
public void testWithdraw(Tester t) {
reset();
t.checkExpect(check1.withdraw(25), 75);
t.checkExpect(check1, new Checking(1, 75, "First Checking Account", 20));
reset();
t.checkExpect(savings1.withdraw(25), 175);
t.checkExpect(savings1, new Savings(4, 175, "First Savings Account", 2.5));
reset();
t.checkExpect(credit1.withdraw(900), 920);
t.checkExpect(credit1, new Credit(8, 920, "First Line of Credit", 999, 5.0));
reset();
t.checkExpect(bank1.withdraw(1, 25), 75);
t.checkExpect(check1, new Checking(1, 75, "First Checking Account", 20));
reset();
t.checkExpect(bank1.withdraw(4, 25), 175);
t.checkExpect(savings1, new Savings(4, 175, "First Savings Account", 2.5));
reset();
t.checkExpect(bank1.withdraw(8, 900), 920);
t.checkExpect(credit1, new Credit(8, 920, "First Line of Credit", 999, 5.0));
}
public void testDeposit(Tester t) {
reset();
t.checkExpect(check1.deposit(25), 125);
t.checkExpect(check1, new Checking(1, 125, "First Checking Account", 20));
reset();
t.checkExpect(savings1.deposit(25), 225);
t.checkExpect(savings1, new Savings(4, 225, "First Savings Account", 2.5));
reset();
t.checkExpect(credit1.deposit(20), 0);
t.checkExpect(credit1, new Credit(8, 0, "First Line of Credit", 999, 5.0));
reset();
t.checkExpect(bank1.deposit(1, 25), 125);
t.checkExpect(check1, new Checking(1, 125, "First Checking Account", 20));
reset();
t.checkExpect(bank1.deposit(4, 25), 225);
t.checkExpect(savings1, new Savings(4, 225, "First Savings Account", 2.5));
reset();
t.checkExpect(bank1.deposit(8, 20), 0);
t.checkExpect(credit1, new Credit(8, 0, "First Line of Credit", 999, 5.0));
reset();
}
public void testAddAccount(Tester t) {
reset();
t.checkExpect(this.bank2.accounts, new MtLoA());
this.bank2.add(check1);
t.checkExpect(this.bank2.accounts, new ConsLoA(check1, new MtLoA()));
this.bank2.add(savings1);
t.checkExpect(this.bank2.accounts, new ConsLoA(savings1, new ConsLoA(check1, new MtLoA())));
}
public void testRemoveAccount(Tester t) {
reset();
t.checkExpect(bank1.accounts,
new ConsLoA(check1, new ConsLoA(savings1, new ConsLoA(credit1, new MtLoA()))));
bank1.removeAccount(1);
t.checkExpect(bank1.accounts,
new ConsLoA(savings1, new ConsLoA(credit1, new MtLoA())));
reset();
bank1.removeAccount(4);
t.checkExpect(bank1.accounts,
new ConsLoA(check1, new ConsLoA(credit1, new MtLoA())));
reset();
bank1.removeAccount(8);
t.checkExpect(bank1.accounts,
new ConsLoA(check1, new ConsLoA(savings1, new MtLoA())));
}
}

View File

@ -0,0 +1,6 @@
// Represents a List of Accounts
public interface ILoA {
public Account find(int accountNum);
public ILoA removeAccount(int accountNum);
}

View File

@ -0,0 +1,12 @@
// Represents the empty List of Accounts
public class MtLoA implements ILoA {
MtLoA() {}
public Account find(int accountNum) {
throw new RuntimeException(accountNum + " cound not be found");
}
public ILoA removeAccount(int accountNum) {
throw new RuntimeException(accountNum + " cound not be found");
}
}

View File

@ -0,0 +1,23 @@
// Represents a savings account
public class Savings extends Account {
double interest; // The interest rate
public Savings(int accountNum, int balance, String name, double interest) {
super(accountNum, balance, name);
this.interest = interest;
}
public int withdraw(int amt) {
if (this.balance < amt) {
throw new RuntimeException(amt + " is not available");
} else {
this.balance = this.balance - amt;
return this.balance;
}
}
public int deposit(int funds) {
this.balance = this.balance + funds;
return this.balance;
}
}

View File

@ -132,7 +132,10 @@ class Examples {
void testConstructors(Tester t) {
initCond();
t.checkException(new RuntimeException("Only one instructor can be added to course"),
c2, "addInstructor", i2);
t.checkException(
new RuntimeException("Only one instructor can be added to course"),
c2,
"addInstructor",
i2);
}
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="/Users/nathanhoward/Documents/Code/OSSU-CS/completedwork/core_programming/02_classbased_design/Jars/tester.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Lect19_Aliasing</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=11

View File

@ -0,0 +1,232 @@
import tester.Tester;
class Person {
String name;
int phone;
Person(String name, int phone) {
this.name = name;
this.phone = phone;
}
// Returns true when the given person has the same name and phone number as this person
boolean samePerson(Person that) {
return this.name.equals(that.name) && this.phone == that.phone;
}
// EFFECT: modifies this person's phone number to be the given one
void changeNum(int newNum) {
this.phone = newNum;
}
}
//interface ILoPerson {
// // Returns true if this list contains a person with the given name
// boolean contains(String name);
// // Finds the person in this list with the given name and returns their phone number,
// // or -1 if no such person is found
// int findPhoneNum(String name);
// //Change the phone number for the person in this list with the given name
// void changePhone(String name, int newNum);
//}
//
//class MtLoPerson implements ILoPerson {
// public boolean contains(String name) {
// return false;
// }
// public int findPhoneNum(String name) {
// return -1;
// }
// public void changePhone(String name, int newNum) {
// return;
// }
//}
//
//class ConsLoPerson implements ILoPerson {
// Person first;
// ILoPerson rest;
// ConsLoPerson(Person first, ILoPerson rest) {
// this.first = first;
// this.rest = rest;
// }
// public boolean contains(String name) {
// if (this.first.name == name) {
// return true;
// } else {
// return this.rest.contains(name);
// }
// }
// public int findPhoneNum(String name) {
// if (this.first.name == name) {
// return this.first.phone;
// } else {
// return this.rest.findPhoneNum(name);
// }
// }
// public void changePhone(String name, int newNum) {
// if (this.first.name.equals(name)) {
// this.first.changeNum(newNum);
// } else {
// this.rest.changePhone(name, newNum);
// }
// }
//}
interface IPred<T> {
boolean apply(T t);
}
class WhichOne implements IPred<Person> {
Person find;
WhichOne(Person find) {
this.find = find;
}
public boolean apply(Person p) {
return p.name == find.name;
}
}
//result type R
interface IFunc<A, R> {
R apply(A input);
}
class WhatToDo implements IFunc<Person, Void> {
int number;
WhatToDo(int number) {
this.number = number;
}
public Void apply(Person p) {
p.changeNum(number);
}
}
interface IList<T> {
//Finds and returns the person in this list matching the given predicate,
//or null if no such person is found
T find(IPred<T> whichOne, IFunc<T, Void> whatToDo);
}
class MtList<T> implements IList<T> {
public Void find(IPred<T> whichOne, IFunc<T, Void> whatToDo) {
return null;
}
}
class ConsList<T> implements IList<T> {
T first;
IList<T> rest;
ConsList(T first, IList<T> rest) {
this.first = first;
this.rest = rest;
}
public T find(IPred<T> whichOne) {
if (whichOne.apply(this.first)) {
return this.first;
} else {
return this.rest.find(whichOne);
}
}
public Void find(IPred<T> whichOne, IFunc<T, Void> whatToDo) {
if (whichOne.apply(this.first)) {
whatToDo.apply(this.first);
} else {
this.rest.find(whichOne, whatToDo);
}
return null;
}
}
class Examples {
Person anne;
Person bob;
Person clyde;
Person dana;
Person eric;
Person frank;
Person gail;
Person henry;
Person irene;
Person jenny;
IList<Person> friends, family, work;
void initData() {
this.anne = new Person("Anne", 1234);
this.bob = new Person("Bob", 3456);
this.clyde = new Person("Clyde", 6789);
this.dana = new Person("Dana", 1357);
this.eric = new Person("Eric", 12469);
this.frank = new Person("Frank", 7294);
this.gail = new Person("Gail", 9345);
this.henry = new Person("Henry", 8602);
this.irene = new Person("Irene", 91302);
this.jenny = new Person("Jenny", 8675309);
// this.friends = new ConsLoPerson(this.anne, new ConsLoPerson(this.clyde,
// new ConsLoPerson(this.gail, new ConsLoPerson(this.frank,
// new ConsLoPerson(this.jenny, new MtLoPerson())))));
// this.family = new ConsLoPerson(this.anne, new ConsLoPerson(this.dana,
// new ConsLoPerson(this.frank, new MtLoPerson())));
// this.work = new ConsLoPerson(this.bob, new ConsLoPerson(this.clyde,
// new ConsLoPerson(this.dana, new ConsLoPerson(this.eric,
// new ConsLoPerson(this.henry, new ConsLoPerson(this.irene,
// new MtLoPerson()))))));
this.friends = new ConsList<Person>(this.anne, new ConsList<Person>(this.clyde,
new ConsList<Person>(this.gail, new ConsList<Person>(this.frank,
new ConsList<Person>(this.jenny, new MtList<Person>())))));
this.family = new ConsList<Person>(this.anne, new ConsList<Person>(this.dana,
new ConsList<Person>(this.frank, new MtList<Person>())));
this.work = new ConsList<Person>(this.bob, new ConsList<Person>(this.clyde,
new ConsList<Person>(this.dana, new ConsList<Person>(this.eric,
new ConsList<Person>(this.henry, new ConsList<Person>(this.irene,
new MtList<Person>()))))));
}
void testFindPhoneNum(Tester t) {
this.initData();
t.checkExpect(this.friends.find("Frank"), 7294);
t.checkExpect(this.family.find("Frank"),
this.friends.find("Frank"));
t.checkExpect(this.frank.phone, 7294);
this.family.changePhone(this.frank, 9021);
t.checkExpect(this.friends.find("Frank"), 9021);
t.checkExpect(this.family.find("Frank"),
this.friends.find("Frank"));
t.checkExpect(this.frank.phone, 9021);
}
// void testFindPhoneNum(Tester t) {
// this.initData();
// t.checkExpect(this.friends.findPhoneNum("Frank"), 7294);
// t.checkExpect(this.family.findPhoneNum("Frank"),
// this.friends.findPhoneNum("Frank"));
// t.checkExpect(this.frank.phone, 7294);
// this.family.changePhone("Frank", 9021);
// t.checkExpect(this.friends.findPhoneNum("Frank"), 9021);
// t.checkExpect(this.family.findPhoneNum("Frank"),
// this.friends.findPhoneNum("Frank"));
// t.checkExpect(this.frank.phone, 9021);
// }
// void testChangeNum(Tester t) {
// this.initData();
// t.checkExpect(this.frank.phone, 7294);
// this.frank.changeNum(9021);
// t.checkExpect(this.frank.phone, 9021);
// }
// void testAliasing(Tester t) {
// // Create two Person objects that are the same
// Person johndoe1 = new Person("John Doe", 12345);
// Person johndoe2 = new Person("John Doe", 12345);
// // Alias johndoe1 to johndoe3
// Person johndoe3 = johndoe1;
//
// // Check that all three John Does are the same according to samePerson
// t.checkExpect(johndoe1.samePerson(johndoe2), true);
// t.checkExpect(johndoe1.samePerson(johndoe3), true);
//
// // Modify johndoe1
// johndoe1.name = "Johnny Deere";
//
// // Now let's try the same tests. Which of them will pass?
// t.checkExpect(johndoe1.samePerson(johndoe2), false);
// t.checkExpect(johndoe1.samePerson(johndoe3), true);
// }
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="/Users/nathanhoward/Documents/Code/OSSU-CS/completedwork/core_programming/02_classbased_design/Jars/tester.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Lect20_MutableDataStructs</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=11

View File

@ -0,0 +1,304 @@
import tester.Tester;
class Person {
String name;
int phone;
Person(String name, int phone) {
this.name = name;
this.phone = phone;
}
// Returns true when the given person has the same name and phone number as this person
boolean samePerson(Person that) {
return this.name.equals(that.name) && this.phone == that.phone;
}
// EFFECT: modifies this person's phone number to be the given one
void changeNum(int newNum) {
this.phone = newNum;
}
}
// Represents a sentinel at the start, a node in the middle,
// or the empty end of a list
abstract class APersonList {
APersonList() {} // nothing to do here
abstract boolean contains(String name);
abstract int findPhoneNum(String name);
abstract void changePhone(String name, int newNum);
abstract void removePerson(String name);
abstract void removePersonHelp(String name, ANode prev);
}
// Represents a node in a list that has some list after it
class ANode extends APersonList {
APersonList rest;
ANode(APersonList rest) {
this.rest = rest;
}
boolean contains(String name) {
return false;
}
int findPhoneNum(String name) {
return -1;
}
void changePhone(String name, int newNum) {
return;
}
void removePerson(String name) {
return;
}
void removePersonHelp(String name, ANode prev) {
return;
}
}
// Represents the dummy node before the first actual node of the list
class Sentinel extends ANode {
Sentinel(APersonList rest) {
super(rest);
}
boolean contains(String name) {
return this.rest.contains(name);
}
int findPhoneNum(String name) {
return this.rest.findPhoneNum(name);
}
void removePerson(String name) {
this.rest.removePersonHelp(name, this);
}
void removePersonHelp(String name, ANode prev) {
throw new RuntimeException("Can't try to remove on a Sentinel!");
}
void addPerson(Person p) {
this.rest = new ConsLoPerson(p, this.rest);
}
}
// Represents the empty end of the list
class MtLoPerson extends APersonList {
public boolean contains(String name) {
return false;
}
public int findPhoneNum(String name) {
return -1;
}
public void changePhone(String name, int newNum) {
return;
}
public void removePerson(String name) {
return;
}
void removePersonHelp(String name, ANode prev) {
return;
}
}
class ConsLoPerson extends ANode {
Person first;
ConsLoPerson(Person data, APersonList rest) {
super(rest);
this.first = data;
}
public boolean contains(String name) {
if (this.first.name == name) {
return true;
} else {
return this.rest.contains(name);
}
}
public int findPhoneNum(String name) {
if (this.first.name == name) {
return this.first.phone;
} else {
return this.rest.findPhoneNum(name);
}
}
public void changePhone(String name, int newNum) {
if (this.first.name.equals(name)) {
this.first.changeNum(newNum);
} else {
this.rest.changePhone(name, newNum);
}
}
public void removePerson(String name) {
this.rest.removePersonHelp(name, this);
}
void removePersonHelp(String name, ANode prev) {
if (this.first.name.equals(name)) {
prev.rest = this.rest;
} else {
this.rest.removePersonHelp(name, this);
}
}
}
class MutablePersonList {
Sentinel sentinel;
MutablePersonList(Sentinel sentinel) {
this.sentinel = sentinel;
}
MutablePersonList() {
this.sentinel = new Sentinel(new MtLoPerson());
}
boolean contains(String name) {
return this.sentinel.contains(name);
}
int findPhoneNum(String name) {
return this.sentinel.findPhoneNum(name);
}
void changePhone(String name, int newNum) {
this.sentinel.changePhone(name, newNum);
}
void removePerson(String name) {
this.sentinel.rest.removePersonHelp(name, this.sentinel);
}
void addPerson(Person p) {
this.sentinel.addPerson(p);
}
}
class Examples {
Person anne;
Person bob;
Person clyde;
Person dana;
Person eric;
Person frank;
Person gail;
Person henry;
Person irene;
Person jenny;
APersonList friends, family, work;
void initData() {
this.anne = new Person("Anne", 1234);
this.bob = new Person("Bob", 3456);
this.clyde = new Person("Clyde", 6789);
this.dana = new Person("Dana", 1357);
this.eric = new Person("Eric", 12469);
this.frank = new Person("Frank", 7294);
this.gail = new Person("Gail", 9345);
this.henry = new Person("Henry", 8602);
this.irene = new Person("Irene", 91302);
this.jenny = new Person("Jenny", 8675309);
this.friends = new ConsLoPerson(this.anne, new ConsLoPerson(this.clyde,
new ConsLoPerson(this.gail, new ConsLoPerson(this.frank,
new ConsLoPerson(this.jenny, new MtLoPerson())))));
this.family = new ConsLoPerson(this.anne, new ConsLoPerson(this.dana,
new ConsLoPerson(this.frank, new MtLoPerson())));
this.work = new ConsLoPerson(this.bob, new ConsLoPerson(this.clyde,
new ConsLoPerson(this.dana, new ConsLoPerson(this.eric,
new ConsLoPerson(this.henry, new ConsLoPerson(this.irene,
new MtLoPerson()))))));
}
void testFindPhoneNum(Tester t) {
this.initData();
t.checkExpect(this.friends.findPhoneNum("Frank"), 7294);
t.checkExpect(this.family.findPhoneNum("Frank"),
this.friends.findPhoneNum("Frank"));
t.checkExpect(this.frank.phone, 7294);
this.family.changePhone("Frank", 9021);
t.checkExpect(this.friends.findPhoneNum("Frank"), 9021);
t.checkExpect(this.family.findPhoneNum("Frank"),
this.friends.findPhoneNum("Frank"));
t.checkExpect(this.frank.phone, 9021);
}
void testChangeNum(Tester t) {
this.initData();
t.checkExpect(this.frank.phone, 7294);
this.frank.changeNum(9021);
t.checkExpect(this.frank.phone, 9021);
}
void testAliasing(Tester t) {
// Create two Person objects that are the same
Person johndoe1 = new Person("John Doe", 12345);
Person johndoe2 = new Person("John Doe", 12345);
// Alias johndoe1 to johndoe3
Person johndoe3 = johndoe1;
// Check that all three John Does are the same according to samePerson
t.checkExpect(johndoe1.samePerson(johndoe2), true);
t.checkExpect(johndoe1.samePerson(johndoe3), true);
// Modify johndoe1
johndoe1.name = "Johnny Deere";
// Now let's try the same tests. Which of them will pass?
t.checkExpect(johndoe1.samePerson(johndoe2), false);
t.checkExpect(johndoe1.samePerson(johndoe3), true);
}
//Tests removing the first person in a list
void testRemoveFirstPerson(Tester t) {
this.initData();
MutablePersonList list1 = new MutablePersonList(
new Sentinel(new ConsLoPerson(this.anne, new ConsLoPerson(this.clyde,
new ConsLoPerson(this.henry, new MtLoPerson())))));
MutablePersonList list2 = new MutablePersonList(
new Sentinel(new ConsLoPerson(this.anne, new ConsLoPerson(this.clyde,
new ConsLoPerson(this.gail, new MtLoPerson())))));
// Check initial conditions
t.checkExpect(list1.contains("Anne"), true);
t.checkExpect(list2.contains("Anne"), true);
// Modify list1
list1.removePerson("Anne");
// Check that list1 has been modified...
t.checkExpect(list1.contains("Anne"), false);
// ...but that list2 has not
t.checkExpect(list2.contains("Anne"), true);
}
//Tests removing a middle person in a list
void testRemoveMiddlePerson(Tester t) {
this.initData();
MutablePersonList list1 = new MutablePersonList(
new Sentinel(new ConsLoPerson(this.anne, new ConsLoPerson(this.clyde,
new ConsLoPerson(this.henry, new MtLoPerson())))));
MutablePersonList list2 = new MutablePersonList(
new Sentinel(new ConsLoPerson(this.dana, new ConsLoPerson(this.clyde,
new ConsLoPerson(this.gail, new MtLoPerson())))));
// Check initial conditions
t.checkExpect(list1.contains("Clyde"), true);
t.checkExpect(list2.contains("Clyde"), true);
// Modify list1
list1.removePerson("Clyde");
// Check that list1 has been modified...
t.checkExpect(list1.contains("Clyde"), false);
// ...but that list2 has not
t.checkExpect(list2.contains("Clyde"), true);
}
//Tests removing the last person in a list
void testRemoveLastPerson(Tester t) {
this.initData();
MutablePersonList list1 = new MutablePersonList(
new Sentinel(new ConsLoPerson(this.anne, new ConsLoPerson(this.clyde,
new ConsLoPerson(this.henry, new MtLoPerson())))));
MutablePersonList list2 = new MutablePersonList(
new Sentinel(new ConsLoPerson(this.dana, new ConsLoPerson(this.clyde,
new ConsLoPerson(this.henry, new MtLoPerson())))));
// Check initial conditions
t.checkExpect(list1.contains("Henry"), true);
t.checkExpect(list2.contains("Henry"), true);
// Modify list1
list1.removePerson("Henry");
// Check that list1 has been modified...
t.checkExpect(list1.contains("Henry"), false);
// ...but that list2 has not
t.checkExpect(list2.contains("Henry"), true);
}
void testAddPerson(Tester t) {
this.initData();
MutablePersonList list1 = new MutablePersonList(
new Sentinel(new ConsLoPerson(this.anne, new ConsLoPerson(this.clyde,
new ConsLoPerson(this.henry, new MtLoPerson())))));
MutablePersonList list2 = new MutablePersonList(
new Sentinel(new ConsLoPerson(this.dana, new ConsLoPerson(this.clyde,
new ConsLoPerson(this.henry, new MtLoPerson())))));
// Check initial conditions
t.checkExpect(list1.contains("Eric"), false);
t.checkExpect(list2.contains("Eric"), false);
// Modify list1
list1.addPerson(this.eric);
// Check that list1 has been modified...
t.checkExpect(list1.contains("Eric"), true);
// ...but that list2 has not
t.checkExpect(list2.contains("Eric"), false);
}
}