/* --- CSU213 Spring 2006 Lecture Notes --------- Copyright 2006 Viera K. Proulx Lecture 9: Take your place in the line... Goals: - Designing methods that sort a list of courses. - Practice using the design recipe in the context of a class hierarchy Introduction: We would like to order a list of courses by the course number. Of course, once we understand how to do this, we should be use the same desing process to design methods that will sort a list of other kinds of objects using another criteria for ordering the list. Let us follow the desing recipe!! 1. Problem analysis. The method 'sort' will be defined in the classes that represent a list of courses. There is nothing else the method needs besides the list of courses that invoked the method. 2. Purpose and Header. We now know what the header will be - and we add the purpose statement: // produce a list sorted by course number from this list of courses abstract ALoCourse sort(); This method needs to be defined in every subclass of the ALoCourse class. 3. Examples. Course lab1 = new Course("CS Lab 1", 212); Course eng1 = new Course("English 1", 128); Course opsys = new Course("Operating Systems", 313); Course biol = new Course("Biology 1", 210); ALoCourse mtcourses = new MTLoCourse(); ALoCourse list1 = new ConsLoCourse(this.lab1, this.mtcourses); ALoCourse list2 = new ConsLoCourse(this.eng1,this.list1); ALoCourse list4 = new ConsLoCourse(this.opsys, new ConsLoCourse(this.biol, this.list2)); mtcourses.sort() --> new MTLoCourse() list1.sort() --> list1 list4.sort() --> new ConsLoCourse(eng1, new ConsLoCourse(biol, new ConsLoCourse(lab1, new ConsLoCourse(opsys, mtcourses)))) 4. Template. Again, there is no data in MTLoCourse, so we only need a template for the class ConsLoCourse: ... this.first ... -- Course ... this.rest ... -- ALoCourse ... this.rest.sort() ... -- ALoCourse (sorted) 5. Body. As usual we try to do the simple case first. class MTLoCourse: ------------- An empty list is sorted, so this is a trivial case: ALoCourse sort(){ return this; } class ConsLoCourse: --------------- ... this.first ... -- Course ... this.rest ... -- ALoCourse ... this.rest.sort() ... -- ALoCourse (sorted) Reading aloud the purpose statement for 'this.rest.sort()' we get: 'produce a list sorted by course number from the rest of this list of courses' So all that reamins is to insert the first item into a sorted rest of the list. We use a helper method: // insert the given Course into this sorted list ALoCourse insert(Course course) and with the help of this method, the body for the 'sort' becomes: return this.rest.sort().insert(this.first); ---------------------------------------------------------------------------- We now work on the helper method 'insert'. We already have the purpose and the header. Examples. mtcourses.insert(tool) --> new ConsLoCourse(tool, mtcourses) list1.insert(eng1) --> new ConsLoCourse(eng1, list1) list1.insert(opsys) --> new ConsLoCourse(help, new ConsLoCourse(opsys, mtcourses)) new ConsLoCourse(eng1, new ConsLoCourse(biol, new ConsLoCourse(opsys, mtcourses))).insert(lab1) --> new ConsLoCourse(eng1, new ConsLoCourse(biol, new ConsLoCourse(lab1, new ConsLoCourse(opsys, mtcourses)))) Template and Body. class MTLoCourse: ------------- The result is always a list with one item: return new ConsLoCourse(course, this); class ConsLoCourse: --------------- We use the earlier template for the class ConsLoCourse ... this.first ... -- Course ... this.rest ... -- ALoCourse ... this.rest.sort() ... -- ALoCourse (sorted) However, we cannot add ... this.rest.insert(Course ...) to the template, because it requires that the instance that invokes the method be already sorted. But we can use this.rest.sort() instead, to invoke the 'insert' method: ... this.rest.sort().insert(Course ...) ... -- ALoCourse (sorted) Reading aloud the combined purpose statement for 'this.rest.insert(Course ...)' we get: 'insert the given Course into the sorted rest of this sorted list' If the given Course has a smaller course number than the first item in the list, the resulting list is just new ConsLoCourse(course, this) otherwise, the first item of the sorted list is the first item of the list we are instering into, and the rest consists of the given Course inserted into the rest of the list: new ConsLoCourse(this.first, this.rest.insert(course)) and the body of the method is: if (course.number < this.first.number) return new ConsLoCourse(course, this); else return new ConsLoCourse(this.first, this.rest.insert(course)); */ // The final code is: /* ; ; ; ; ;;;; ; ; ; ; ; ; ; ; ; ; ;;; ;; ; ;;; ; ; ; ; ; ;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;;;;;; ; ; ; ; ; ; ; ; ; ; ; ; ; ;; ; ; ;;;; ;;; ;; ; ;;;; ; ; ; */ /* +-----------+ | ALoCourse |<----------------+ +-----------+ | +-----------+ | / \ | | | - - - - - - - - - - | | | | +------------+ +----------------+ | | MTLoCourse | | ConsLoCourse | | +------------+ +----------------+ | +------------+ +-| Course first | | | | ALoCourse rest |--+ | +----------------+ | v +---------------------------+ | Course | +---------------------------+ | String title | | int number | +---------------------------+ +---------------------------+ */ // to represent a Course class Course { String title; int number; Course(String title, int number) { this.title = title; this.number = number; } boolean same(Course that){ return this.title.equals(that.title) && this.number == that.number; } } // to represent a list of Courses abstract class ALoCourse { // determine whether this list of Courses is the same as the given one abstract boolean same(ALoCourse that); // determine whether this list is the same as given MTLoCourse list abstract boolean sameMTLoCourse(MTLoCourse other); // determine whether this list is the same as given ConsLoCourse list abstract boolean sameConsLoCourse(ConsLoCourse other); // sort this list of Courses in ascending order of the number of number abstract ALoCourse sort(); // insert the given Course into this sorted list abstract ALoCourse insert(Course course); } // to represent an empty llist of Courses class MTLoCourse extends ALoCourse { MTLoCourse() {} // determine whether this list of Courses is the same as the given one boolean same(ALoCourse that){ return that.sameMTLoCourse(this); } // determine whether this list is the same as given MTLoCourse list boolean sameMTLoCourse(MTLoCourse other){ return true; } // determine whether this list is the same as given ConsLoCourse list boolean sameConsLoCourse(ConsLoCourse other){ return false; } ALoCourse sort(){ return this; } ALoCourse insert(Course course){ return new ConsLoCourse(course, this); } } // to represnet a non-empty list of Courses class ConsLoCourse extends ALoCourse { Course first; ALoCourse rest; ConsLoCourse(Course first, ALoCourse rest) { this.first = first; this.rest = rest; } // determine whether this list of Courses is the same as the given one boolean same(ALoCourse that){ return that.sameConsLoCourse(this); } // determine whether this list is the same as given MTLoCourse list boolean sameMTLoCourse(MTLoCourse other){ return false; } // determine whether this list is the same as given ConsLoCourse list boolean sameConsLoCourse(ConsLoCourse other){ return this.first.same(other.first) && this.rest.same(other.rest); } ALoCourse sort(){ return this.rest.sort().insert(this.first); } ALoCourse insert(Course course){ if (course.number < this.first.number) return new ConsLoCourse(course, this); else return new ConsLoCourse(this.first, this.rest.insert(course)); } } class Examples { Examples(){} Course lab1 = new Course("CS Lab 1", 212); Course eng1 = new Course("English 1", 128); Course opsys = new Course("Operating Systems", 313); Course biol = new Course("Biology 1", 210); ALoCourse mtcourses = new MTLoCourse(); ALoCourse list1 = new ConsLoCourse(this.lab1, this.mtcourses); ALoCourse list2 = new ConsLoCourse(this.eng1,this.list1); ALoCourse list4 = new ConsLoCourse(this.opsys, new ConsLoCourse(this.biol, this.list2)); // test the method insert boolean testInsert(){ return this.mtcourses.insert(this.opsys).same(new ConsLoCourse(this.opsys, this.mtcourses)) && this.list1.insert(this.eng1).same(new ConsLoCourse(this.eng1, this.list1)) && this.list1.insert(this.opsys).same(new ConsLoCourse(this.lab1, new ConsLoCourse(this.opsys, this.mtcourses))) && new ConsLoCourse(this.eng1, new ConsLoCourse(this.biol, new ConsLoCourse(this.opsys, this.mtcourses))).insert(this.lab1).same (new ConsLoCourse(this.eng1, new ConsLoCourse(this.biol, new ConsLoCourse(this.lab1, new ConsLoCourse(this.opsys,this.mtcourses))))); } boolean testSort(){ return this.mtcourses.sort().same(new MTLoCourse()) && this.list1.sort().same(this.list1) && this.list4.sort().same(new ConsLoCourse(this.eng1, new ConsLoCourse(this.biol, new ConsLoCourse(this.lab1, new ConsLoCourse(this.opsys, this.mtcourses))))); } boolean testAll(){ return this.testInsert() && this.testSort(); } }