mirror of
https://github.com/ossu/computer-science.git
synced 2026-04-11 14:21:57 +08:00
Mutation
This commit is contained in:
parent
c29c430d45
commit
46c70b26f8
@ -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>
|
||||
@ -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>
|
||||
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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:
|
||||
*
|
||||
*/
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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())));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
|
||||
// Represents a List of Accounts
|
||||
public interface ILoA {
|
||||
public Account find(int accountNum);
|
||||
public ILoA removeAccount(int accountNum);
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@ -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
|
||||
@ -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);
|
||||
// }
|
||||
|
||||
}
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user