Today's tutorial covers two topics that are central to your success on the final assignment: two-dimensional arrays and polymorphism. These were covered in lecture modules 10 and ll (see handouts).

- Double Arrays
`GradeBook(String[])`

: Constructor from a list of student names`int numAssignments()`

: Get num. of assignments so far`int numStudents()`

: Get num. of students in the book`addAssignment(int[],int)`

: Add a new assignment with the given scores for the students`int getMark(String,int)`

: Get a student's mark on a single assignment`changeMark(String,int,int)`

: Change a student's mark on a single assignment`double avgMark(int)`

: Get the average mark on a given assignment`double studentAvg(String)`

: Get the given student's average over all assignments`String topStudent()`

: Get the name of the student with the highest average`curveAssignment(int)`

: Curve all the marks on a given assignment to the highest mark.- Polymorphism
- Refactoring
- New Sequences
- Another interface

We will be implementing a class `GradeBook`

, which stores marks
for a number of students for a number of assignments by using a 2D array.
Stored are the names of each student, the marks of each student on each
assignment (the 2D array), and the maximum score for each assignment.
The methods you are to implement are:

Details for these methods can be found in the comments of the skeleton
code. The first 6 methods (including constructor) must be implemented for the
tests to function properly. Then you can try implementing any of the other
methods and test your implementation with the provided
`GradeBookTest`

class.

Included in the skeleton code are two classes, `Sequence`

and `SequenceUtils`

. The first is a class to represent arithmetic
sequences, with an iterator-like implementation. `SequenceUtils`

just contains a few methods to perform some basic operations on a given
`Sequence`

object.

Now suppose we want to be able to handle any kind of sequences, not just
arithmetic ones. To accomplish this *without modifying the
SequenceUtils class*, rewrite

`Sequence`

to be an
interface and make a new class called `ArithmeticSeq`

that
implements this interface.Now we can actually add new sequence classes. Some ideas are Geometric
Sequences (i.e. of the form <a,ab,ab^{2},ab^{3},...>)
and the Fibonacci sequence.

Notice that the `sumFirst`

method in `SequenceUtils`

is actually calling `next()`

k times and adding up the results. But
for some sequences, such as arithmetic and geometric, we can actually compute
this sum explicitly with formulas.

To handle this, make a new interface
`SummableSeq`

that is a sub-interface of `Sequence`

,
with just one method, `int sumFirst(int k)`

. Then make your
arithmetic and geometric sequence classes implement this interface.

Finally, we have to add code to the `SequenceUtils`

class
to recognize `SummableSeq`

arguments and handle them more
efficiently. One solution is to override the `sumFirst`

method
by writing another method with signature

`public static int sumFirst(SummableSeq ss, int k)`

The problem with this is when we have something like:

Sequence s = new ArithmeticSeq(2,3); SequenceUtils.sumFirst(s,10); // doesn't call sumFirst in ArithmeticSeq!

What is happening here and why? Now use the `instanceof`

operator
in the original `sumFirst`

method to handle this and make everything
work just like we want.

Last modified on Wednesday, 09 January 2019, at 14:31 hours.