/*********************************************** * CS2510 Spring 2011 * Lecture #13.3 * State Chang: changing a list ***********************************************/ /** Goal: change the phone number for a given person */ import tester.Tester; /* +-----------+ | ILoPerson |<------------+ +-----------+ | +-----------+ | / \ | --- | | | ------------------- | | | | +------------+ +----------------+ | | MTLoObject | | ConsLoObject | | +------------+ +----------------+ | +------------+ +-| Object first | | | | ILoObject rest |-+ | +----------------+ v +-------------+ | Person | +-------------+ | String name | | int phone | +-------------+ */ // to represent a person in a contacts list class Person{ String name; int phone; Person(String name, int phone){ this.name = name; this.phone = phone; } // EFFECT: // change the phone number of this person to the given one void newPhone(int newNumber){ this.phone = newNumber; } // is this the same person as the given person? boolean samePerson(Person that){ return this.name.equals(that.name) && this.phone == that.phone; } } // to represent a list of Person-s interface ILoPerson{ // to compute the size of this list public int size(); // is the given person in this list? public boolean contains (Person that); // EFFECT: // change the phone number for the given person // to the given number public void changePhone(String name, int phone); // EFFECT: // add a new person to this list public void addPerson(Person p); // EFFECT: // remove the given person from this list public void removePerson(Person p); } // to represent an empty list of person contacts class MtLoPerson implements ILoPerson{ MtLoPerson() {} // compute the size of this empty list of persons public int size(){ return 0; } // does this empty list contain the given person? public boolean contains (Person that){ return false; } // EFFECT: // change the phone number for the given person // to the given number public void changePhone(String name, int phone){ throw new RuntimeException("No person with the given name in our list"); } // EFFECT: // add a new person to this list public void addPerson(Person p){ //this = new ConsLoPerson(p, this); } // EFFECT: // remove the given person from this list public void removePerson(Person p){ throw new RuntimeException("No person with the given name in our list"); } } class ConsLoPerson implements ILoPerson{ Person first; ILoPerson rest; ConsLoPerson(Person first, ILoPerson rest){ this.first = first; this.rest = rest; } /* TEMPLATE: ... this.first ... -- Person ... this.rest ... -- ILoPerson ... this.rest.size() ... -- int ... this.rest.contains( Object ) ... -- boolean */ public int size(){ return 1 + this.rest.size(); } // does this list contain the given person? public boolean contains (Person that){ return this.first.samePerson(that) || this.rest.contains(that); } // EFFECT: // change the phone number for the given person // to the given number in this list public void changePhone(String name, int phone){ if (this.first.name.equals(name)){ this.first.newPhone(phone); } else this.rest.changePhone(name, phone); } // EFFECT: // add a new person to this list public void addPerson(Person p){ this.rest = new ConsLoPerson(p, this.rest); } // EFFECT: // remove the given person from this list public void removePerson(Person p){ if (this.first.samePerson(p)){ //this = this.rest; } else { this.rest.removePerson(p); } } } // Examples for a list of contacts class Examples{ Examples () {} Person bill = new Person("Bill", 2345); Person matt = new Person("Matt", 1234); Person anne = new Person("Anne", 7896); Person anne1 = new Person("Anne", 7896); Person john = new Person("John", 8866); Person john1 = this.john; Person jane = new Person("Jane", 3456); // reset the value of each person, making a new Person instance for each void resetNewPersons(){ this.bill = new Person("Bill", 2345); this.matt = new Person("Matt", 1234); this.anne = new Person("Anne", 7896); this.anne1 = new Person("Anne", 7896); this.john = new Person("John", 8866); this.john1 = this.john; this.jane = new Person("Jane", 3456); } // reset each person's name and phone number to the original one void resetMutatePersons(){ this.bill.name = "Bill"; this.bill.phone = 2345; this.matt.name = "Name"; this.matt.phone = 1234; this.anne.name = "Anne"; this.anne.phone = 7896; this.anne1.name = "Anne"; this.anne1.phone = 7896; this.john.name = "John"; this.john.phone = 8866; this.john1.name = "John"; this.john1 = this.john; this.jane.name = "Jane"; this.jane.phone = 3456; } // test the method newPhone for the Person class // start with a new local value, no need to reset void testNewPhoneV1(Tester t){ // setup Person jill = new Person("Jill", 3456); // run the method jill.newPhone(1234); // run the test: verify the values for 'jill' t.checkExpect(jill, new Person("Jill", 1234)); // no need to reset - we only used a local variable } // test the method newPhone for the Person class void testNewPhoneV2(Tester t){ // setup not needed, we use the data already defined // run the method this.john.newPhone(1234); // run the test t.checkExpect(this.john, new Person("John", 1234)); // reset: bad version, makes a new instance of john this.john = new Person("John", 8866); // the value of 'john1' is still the changed one: t.checkExpect(this.john, new Person("John", 8866)); t.checkExpect(this.john1, new Person("John", 1234)); } ILoPerson mtphlist = new MtLoPerson(); ILoPerson family = new ConsLoPerson(this.bill, new ConsLoPerson(this.matt, new ConsLoPerson(this.anne, this.mtphlist))); ILoPerson familyNewAnne = new ConsLoPerson(this.bill, new ConsLoPerson(this.matt, new ConsLoPerson(new Person("Anne", 4444), this.mtphlist))); ILoPerson friends = new ConsLoPerson(this.anne, new ConsLoPerson(this.john, this.mtphlist)); ILoPerson friendsOldAnne = new ConsLoPerson(new Person("Anne", 7896), new ConsLoPerson(this.john, this.mtphlist)); ILoPerson work = new ConsLoPerson(this.john1, new ConsLoPerson(this.jane, this.mtphlist)); ILoPerson all = new ConsLoPerson(this.bill, new ConsLoPerson(this.matt, new ConsLoPerson(this.anne, new ConsLoPerson(this.john, new ConsLoPerson(this.jane, this.mtphlist))))); // test the method contains for a list of contacts void testContains(Tester t){ t.checkExpect(this.mtphlist.contains(this.bill), false); t.checkExpect(this.family.contains(this.matt), true); t.checkExpect(this.friends.contains(bill), false); } // test the method changePhone for a list of contacts // We produce a new list with the changed phone number and test that it // is what we expect. // We test changing the phone for nonexisting person and verify that it // will raise an exception // We test the effects on various lists - as we have done before // // We then reset all Person data to their original values and verify // that the earlier tests work as they did before. void testChangePhone(Tester t){ // change the phone number for Anne in the family list and test it: this.family.changePhone("Anne", 4444); t.checkExpect(this.family, this.familyNewAnne); t.checkExpect(this.anne, new Person("Anne", 4444)); // test that an exception is thrown for missing entry t.checkException( new RuntimeException("No person with the given name in our list"), this.work, "changePhone", "Anne", 4444); // verify that the family has the right number for Anne: t.checkExpect(this.family.contains(new Person("Anne", 7896)), false); t.checkExpect(this.family.contains(new Person("Anne", 4444)), true); // and friends know about it too t.checkExpect(this.friends.contains(new Person("Anne", 4444)), true); // but friendsOldAnne list had a different instance of Anne // and that one did not change t.checkExpect(this.friendsOldAnne.contains(new Person("Anne", 7896)), true); // we now reset the values of all Person-s to the original ones this.resetMutatePersons(); // and the family has the original number for Anne: t.checkExpect(this.family.contains(new Person("Anne", 7896)), true); t.checkExpect(this.family.contains(new Person("Anne", 4444)), false); // and friends know about it too t.checkExpect(this.friends.contains(new Person("Anne", 7896)), true); // but familyNewAnne list had a different instance of Anne // and that one did not change and is still the new one t.checkExpect(this.familyNewAnne.contains(new Person("Anne", 4444)), true); } // test the method contains for a list of contacts - OK after the reset void testContains2(Tester t){ t.checkExpect(this.friends, this.friendsOldAnne); t.checkFail(this.friends.contains(new Person("Anne", 4444)), true); t.checkExpect(this.friends.contains(new Person("Anne", 7896)), true); } // a basic test to the methods addPerson and removePerson for ILoPerson void testAdd(Tester t){ this.mtphlist.addPerson(this.bill); // the test below will fail - no changes could be done to empty list t.checkFail(this.mtphlist.contains(new Person("Bill", 2345)), true); this.friends.addPerson(this.bill); // here the add works OK t.checkExpect(this.friends.contains(new Person("Bill", 2345)), true); // but the remove does not this.friends.removePerson(new Person("Bill", 2345)); t.checkFail(this.friends.contains(new Person("Bill", 2345)), false); } }