/*********************************************** * CS2510 Fall 2011 * Lecture #11 * Function-Classes/Objects (2) ***********************************************/ import tester.*; // Student: Represents a student with identifying data class Student { String name; double gpa; boolean graduating; /** * Template * * Fields: * this.name -- String * this.gpa -- double * this.graduating -- boolean * Methods: * this.graduate -- Student */ Student(String name, double gpa, boolean graduating) { this.name = name; this.gpa = gpa; this.graduating = graduating; } // Returns this student with graduating set to true Student graduate() { return new Student(this.name, this.gpa, true); } } // Represents a list of students interface ILoS { /** * Template * * Methods: * this.insertByComp(Student, IComp) -- ILoS * this.sortByComp(IComp) -- ILoS * this.filter(IFilter) -- ILoS * this.find(IFilter) -- Student */ // insertByComp: Inserts a student into this *sorted* list in the correct // position according to the comparator public ILoS insertByComp(Student s, IComp decider); // sortByComp: Sorts this list by the comparator public ILoS sortByComp(IComp decider); // filter: Filters out students according to the given picker method public ILoS filter(IFilter picker); // find: Returns a student that satisfies our picker public Student find(IFilter picker); } // MtLoS: The empty element in a student list class MtLoS implements ILoS { /** * Template * * Methods: * this.insertByComp(Student, IComp) -- ILoS * this.sortByComp(IComp) -- ILoS * this.filter(IFilter) -- ILoS * this.find(IFilter) -- Student */ // Creates a new cons as there is nothing to compare in an empty list public ILoS insertByComp(Student s, IComp decider) { return new ConsLoS(s,this); } // Nothing to sort, return this public ILoS sortByComp(IComp decider) { return this; } // filter: Returns the empty list, nothing to filter public ILoS filter(IFilter picker) { return this; } // find: Couldn't find student, throws error public Student find(IFilter picker) { throw new RuntimeException("Couldn't find student."); } } //ConsLoS: This cons element in a student list class ConsLoS implements ILoS { Student first; ILoS rest; /** * Template * * Fields: * this.first -- Student * this.rest -- ILoS * Methods: * this.insertByComp(Student, IComp) -- ILoS * this.sortByComp(IComp) -- ILoS * this.filter(IFilter) -- ILoS * this.find(IFilter) -- Student */ ConsLoS(Student first, ILoS rest) { this.first = first; this.rest = rest; } // insertByComp: Inserts a new student into our *sorted* list // using the decider for comparison public ILoS insertByComp(Student s, IComp decider) { if(decider.lessThan(s,first)) { return new ConsLoS(s,this); } else { return new ConsLoS(first, rest.insertByComp(s,decider)); } } // sortByComp: Sorts this element and the recurses based on the decider public ILoS sortByComp(IComp decider) { return rest.sortByComp(decider).insertByComp(first, decider); } // filter: Returns a list of students for which the picker returns true public ILoS filter(IFilter picker) { if (! picker.pick(first)) { return rest.filter(picker); } else { return new ConsLoS(first,rest.filter(picker)); } } // find : Returns the student in this list if it matches the picker public Student find(IFilter picker) { if (picker.pick(first)) { return first; } else { return rest.find(picker); } } } // IComp: Comparison class interface IComp { /** * Template * * Fields: * Methods: * this.lessThan(Student, Student) -- boolean */ // lessThan: Returns true if s1 < s2 for the given // comparison operation public boolean lessThan(Student s1, Student s2); } // CompByName: A comparator for sorting alphanumerically by name class CompByName implements IComp { /** * Template * * Fields: * Methods: * this.lessThan(Student, Student) -- boolean */ // lessThan: Returns true is s1.name sorts before s2.name public boolean lessThan(Student s1, Student s2) { return (s1.name.compareTo(s2.name) < 0); } } //CompByName: A comparator for sorting numerically by gpa class CompByGPA implements IComp { /** * Template * * Fields: * Methods: * this.lessThan(Student, Student) -- boolean */ // lessThan: Returns true is s1.gpa is less than s2.gpa public boolean lessThan(Student s1, Student s2) { return (s1.gpa < s2.gpa); } } // IFilter: A filter based on arbitrary criteria interface IFilter { /** * Template * * Methods: * this.pick(Student) -- boolean */ // pick : Returns true if we should keep this student // false otherwise public boolean pick(Student s); } // Filters out (removes) all graduating students class FilterByGraduating implements IFilter { /** * Template * * Methods: * this.pick(Student) -- boolean */ // pick: Returns true if the student is not graduating // false otherwise public boolean pick(Student s) { return ! s.graduating; } } // Finds (keeps) all graduating students class FindGraduating extends FilterByGraduating { // Do the opposite of our filter public boolean pick(Student s) { return ! super.pick(s); } } // Filters out (removes) students who fall between min and max gpa class FilterByMinMaxGPA implements IFilter { double min; double max; /** * Template * Fields: * this.min -- double * this.max -- double * Methods * this.pick(Student) -- boolean */ FilterByMinMaxGPA(double min, double max) { this.min = min; this.max = max; } // pick : Returns true if student's gpa is outside the range // false otherwise public boolean pick(Student s) { return (s.gpa > max || s.gpa < min); } } // Examples for the Students and lists class StudentExamples { // Some example students Student kev = new Student("Kevin",3.4,false); Student spenc = new Student("Spencer",2.9,false); Student maria = new Student("Maria",3.7,true); Student saad = new Student("Saad",1.2,true); String stattag = kev.name + ": " + kev.gpa; // Comparator examples IComp byname = new CompByName(); IComp bygpa = new CompByGPA(); // List examples ILoS mtS = new MtLoS(); ILoS mlist = new ConsLoS(maria,mtS); ILoS spke = new ConsLoS(spenc,new ConsLoS(kev,mtS)); ILoS kesp = new ConsLoS(kev,new ConsLoS(spenc,mtS)); ILoS students = new ConsLoS(kev, new ConsLoS(spenc, new ConsLoS(maria,mtS))); ILoS studentssort = new ConsLoS(kev, new ConsLoS(maria, new ConsLoS(spenc,mtS))); ILoS studentssortgpa = new ConsLoS(spenc, new ConsLoS(kev, new ConsLoS(maria,mtS))); // Full roster and roster filtered by mid gpa ILoS roster = new ConsLoS(saad,studentssort); ILoS rosternomidgpa = new ConsLoS(saad,mlist); // Filtering examples/test IFilter filtergrad = new FilterByGraduating(); IFilter filtergpa = new FilterByMinMaxGPA(2.0,3.5); IFilter findgrad = new FindGraduating(); // Tests our Graduating filter boolean testFilterGraduating (Tester t) { return t.checkExpect(studentssort.filter(filtergrad), kesp) && t.checkExpect(mtS.filter(filtergrad),mtS) && t.checkExpect(mlist.filter(filtergrad),mtS); } // Tests our GPA filter boolean testFilterGPA (Tester t) { return t.checkExpect(roster.filter(filtergpa), rosternomidgpa) && t.checkExpect(mtS.filter(filtergpa),mtS) && t.checkExpect(mlist.filter(filtergpa),mlist); } // Tests our find with Graduating picker boolean testFindGraduating(Tester t) { return t.checkExpect(roster.find(findgrad), saad) && t.checkExpect(students.find(findgrad), maria) && t.checkException(new RuntimeException("Couldn't find student."), mtS, "find", findgrad); } // Test our comparator boolean testLessThan(Tester t) { return t.checkExpect(byname.lessThan(kev,spenc),true) && t.checkExpect(byname.lessThan(spenc, maria),false) && t.checkExpect(byname.lessThan(spenc, kev),false); } // Test our insertion function boolean testInsert(Tester t) { return t.checkExpect(mtS.insertByComp(kev, byname),new ConsLoS(kev,mtS)) && t.checkExpect(kesp.insertByComp(maria, byname),studentssort) && t.checkExpect(mlist.insertByComp(kev, byname), new ConsLoS(kev,mlist)); } // Test our Sorting function boolean testSort(Tester t) { return t.checkExpect(students.sortByComp(byname),studentssort) && t.checkExpect(students.sortByComp(bygpa),studentssortgpa) ; } }