---
# System prepended metadata

title: 'Homework 2: Abstract Classes, Lists, and Mutation'
tags: [Homeworks-Summer21]

---

---
tags: Homeworks-Summer21
---
# Homework 2: Abstract Classes, Lists, and Mutation
### Due: May 28, 2021 (Anywhere on Earth)
## Learning Objectives
* Explain tradeoffs between mutable and immutable data structures in the context of a specific problem
* Write programs that can compile and run against a provided interface

## Assignment Link
Using [this github classroom link](https://classroom.github.com/a/qdDdc9V-), accept the assignment and clone on your machine. 

If you're having trouble with IntelliJ, check out our [IntelliJ Common Problems](https://hackmd.io/webHvA8yTCqGOAKXYgrI_A) handout.

Please make sure to read [our gradescope submission guide](https://hackmd.io/jC-SEMn_RpiGqMH_EhsDMw) before handing in your assignment!
## Handing In

Begin by cloning the github repository found by clicking the above github classroom link. The following files should be in the `sol` directory. You may replace files we've provided with files you have written last week, but we've provided their implementation if you need help.

* `AbsList.java` containing public abstract class `AbsList`
* `IList.java` containing public interface `IList`
* `EmptyList.java` containing public class `EmptyList`
* `NodeList.java` containing public class `NodeList`
* `Course.java` containing public class `Course`
* `Faculty.java` containing public class `Faculty`
* `Student.java` containing public class `Student`
* `GradeReport.java` containing public class `GradeReport`
* `IGrade.java` containing public interface `IGrade`
* `LetterGrade.java` containing public class `LetterGrade`
* `SNCGrade.java` containing public class `SNCGrade`
* `Homework2TestSuite.java` containing public class `Homework2TestSuite`
* `AutograderCompatibility.java` containing public class `AutograderCompatibility`

After completing this assignment, you should be ready to turn in the following solution files:
* `AbsList.java` containing public abstract class `AbsList`
* `IList.java` containing public interface `IList`
* `EmptyList.java` containing public class `EmptyList`
* `NodeList.java` containing public class `NodeList`
* `Course.java` containing public class `Course`
* `Person.java` containing public abstract class `Person`
* `Faculty.java` containing public class `Faculty`
* `Student.java` containing public class `Student`
* `TA.java` containing public class `TA`
* `GradeReport.java` containing public class `GradeReport`
* `IGrade.java` containing public interface `IGrade`
* `LetterGrade.java` containing public class `LetterGrade`
* `SNCGrade.java` containing public class `SNCGrade`
* `Homework2TestSuite.java` containing public class `Homework2TestSuite`
* `MutationQuestions.txt`
* `GradeReportMemoryDiagram.jpg`
* `ShallowCopyLayout.jpg`
* `DeepCopyLayout.jpg`


**You may include other classes, interfaces, and abstract classes.**

To hand in your files, submit them to Gradescope. Please make sure that `MutationQuestions.txt` is a plain text file, not a rich text file (you can check this by opening your submission in Gradescope and verifying that `MutationQuestons.txt` is readable). 

Once you have handed in your homework, you should receive an email, more or less immediately, confirming that fact. If you don’t receive this email, try handing in again, or ask the TAs what went wrong.

You may have noticed a class `AutograderCompatibility`. Using this class is not required, but might help you debug if Gradescope tells you something along the lines of "The autograder failed to execute correctly." If Gradescope doesn't tell you "works with autograder" after it has finished running, try uncommenting the main method of `AutograderCompatibility` and check that it compiles and runs.

**Note:** If your code does not work with the autograder, you will be penalized. If Gradescope says that your code doesn’t work with our autograder, first, try running `AutograderCompatibility`. If that doesn't work, *then* you may come to hours or post on Ed.


## Testing
Make sure to test your code iteratively as you work! Testing and good code design make up a lot of your grade for this homework. Put your testing in the file `Homework2TestSuite.java`.

You should submit `Homework2TestSuite.java` to the **Homework 2: Testing** assignment on Gradescope. See [our gradescope submission guide](https://hackmd.io/@cs18-spring-2021/HkESq1uJd) for an explanation on how we are grading your tests, and how you can use the Testing assignment on Gradescope to get a better understanding of the assignment.

**Note**: When writing your test suite, you should test only the methods we have asked you to write in this handout. Do not reference in your tests fields or methods that are not required by the assignment, or the wheat and chaff autograder may fail.

# Problems

## Showtime (The Hunt Continues...) 
:::spoiler Optional theme material
The musical *Blueno and Juliet* by Oscar Orwell Peterson (known to his fans as O.O.P.) is coming to Brown and everyone wants tickets! Due to COVID restrictions, seats are in limited supply. Regular ticket sales have already sold out! Do not fret, because Professor Fisler can also award tickets to students who show up on time to their labs. 

You show up on time to your first lab and your lab TA hands you a ticket and the show's playbill. You flip the ticket over to reveal another cryptic Blueno limerick:

*Tonight's players bid Blueno farewell*
*Come see what grim stories they'll tell*
*Of a blue metal bear*
*In a doomed love affair*
*By following the bill's URL*

![](https://i.imgur.com/LcqNQUS.jpg)


(Use tinyurl.com/blueno-and-juliet :))
:::
## Making our Course Classes More Realistic

In Homework 1, we set up basic classes for Courses, Faculty, and Students. With this homework, we will make this setup more realistic by adding the following features:

- Gradebooks with grades for multiple students
- TAs (students who can also help with grading)
- Students changing their registered courses
- Some basic protections for accessing course grades

These features leverage abstract classes, our functional-style list implementation, and field mutation (the lectures from Wed 5/19-Mon 5/24). Tasks that need the material from Mon 5/24 are marked accordingly.

## Gradebooks

Start by making two modifications to the starter classes:

**Task:** Modify the `IList`, `AbsList`, `NodeList`, and `EmptyList` classes from the initial code to have `GradeReport` as the type of the list elements. 

**Task:** Modify the `Course` class to have a field `gradebook`, which is an `IList` of `GradeReport` objects. This field should be set to be an empty list in the constructor. (Use our functional-based implementation, not built-in Java lists.)

### Finding Students in a Gradebook

**Task:** Fill in the method `findStudent` in `NodeList` and `EmptyList`. The method should take a name (String) and return the `GradeReport` for the named student. If the student is not found, have the method throw a `RuntimeException` with the message `"student <NAME> not found"`, where `<NAME>` is replaced with the name that was searched for.

**Study Question:** Could we just as easily have returned `false` if a student is not found?

### Copying Gradebooks

Grades get updated throughout the semester. Having a record of previous gradebook versions is useful for reconstructing grading information if needed (and for testing functions that might otherwise change the grades). 

To support these situations, you'll write two methods to make copies of a gradebook (many programming languages refer to this as “cloning”). There are generally two levels of cloning lists: one ("shallow copy") makes new objects for the nodes, but reuses objects that form the contents; the other ("deep copy") makes new objects for each of the nodes and the contents (in this case, the `GradeReports`).

**Task:** Fill in `shallowCopy` from the stencil in `EmptyList` and `NodeList` so that it returns a list with new nodes but the same `GradeReport` objects as the original. 

**Task:** Fill in `deepCopy` from the stencil in `EmptyList` and `NodeList` so that it returns a list with new objects for each of the nodes, the `GradeReport` objects, and the `LetterGrade` and `SNCGrade` objects. Reuse the existing `Student` and `Course` objects from the input list.

:::info
**Hint:** You may add methods to your existing classes to help you with your copying! 
:::

## Adding TAs

In homework 1, we had students and faculty, but we omitted your invaluable TAs. TAs are interesting because they are students, but they have some of the same permissions that faculty do. We want to add them to our grading system.

**Task:** Create a new class`TA`, in its own file. TAs should be students, but with an additional field called `assisting` that is of type `Course`. Create a constructor for the `TA` class that takes the TA's name, the two `Course`s that they are taking as students, and the `Course` that they are assisting on. TAs shouldn't be able to assist with a class they're taking, so raise a `IllegalArgumentException` with the message `"Cannot take and assist the same course"` if this is the case.

**Study Question:** Why did we make `TA` a subclass of `Student` rather than `Faculty`, given that TAs have elements of each of the other roles?

**Task:** TAs, like faculty, should be able to look up grades for courses on which they are assisting. Modify your code so that both the `Faculty` and `TA` classes have a `viewGrade` method, but this method is not available for students who are not TAs.

**Task:** Add a method called `gradeLookup` to the `Course` class. The method should take a `Faculty` or `TA` object and a student name as input. 
* If `gradebook` has a  `GradeReport` that matches the provided name, the method should return a `String` containing the grade. 
* If no such grade is found, a `RuntimeException` with the message `"student <NAME> not found"` should be thrown (where `"<NAME>"` is replace with the student name being searched for). 
* if the `Faculty` or `TA` does not have permission to view the student's grade, a `RuntimeException` should be thrown. 

Part of the point of the question is for you to think about how to take an argument that can be `Faculty` or `TA`, but not a general `Student`. (We've already covered everything you need in order to do this.)

**Study Question:** Should the `gradeLookup` method include a check that the person trying to view the grade is not a non-TA student? Why or why not?

## Sharing Name Fields

**Task:** At this point, each of the `Faculty`, `Student`, and `TA` classes have fields for a person's name. Create a new abstract superclass (parent class) called `Person` that shares the `name` field across these three classes. When you are done, your class hierarchy should match the following picture:

![](https://i.imgur.com/SyPILdw.png)


**Study Question:** Why did we make the `Person` class abstract? What does the `abstract` annotation allow or prohibit regarding the `Person` class?

## Adding and Changing Grades

:::warning
We will cover the material for this in class on Monday 5/24.
:::

**Task:** Add a method named `storeGrade` to the `Course` class. The method should take in a`Student` and a valid grade (`LetterGrade` or `SNCGrade` from homework 1). The method should result in updating the `Course`'s `gradebook` with a new list that has a new `GradeReport` being added to the original `gradebook` list.

**Task:** Add a method named `updateGrade` to the `Course` class. The method should take the name of a student (String) and a valid grade (`LetterGrade` or `SNCgrade` from homework 1). The method should result in the new grade being stored in the gradebook, without changing the enclosing list itself.
<!-- TODO: this wording is confusing ^ --->

## Students Dropping Courses

:::warning
We will cover the material for this in class on Monday 5/24.
:::

**Task:** Add a method named `dropCourse` to the `Student` class. The method should take a `Course` object as input. 
- If the student is taking the given Course, the corresponding field should be set to `null` and the student's grade information should be removed from the `gradebook` for the inputted course.
- If the student is NOT taking the given Course, throw a `RuntimeException` with the message `"not taking course"`.

Your method should find the student is "taking the course" if the department and number of the given `Course` match the department and number of one of the courses that the student is taking. To help check this, include an `equals` method in the`Course` class that checks these two fields.

**Note:** make sure to change uses of `==` with `Course`s (like in `Student` or `TA`) to `.equals()` now that you have implemented an `equals` method for `Course`! Check out [this EdStem post](https://edstem.org/us/courses/5623/discussion/446448) for more information about the difference between `==` and `.equals()`.

**Study Question:** Does the current `dropCourse` change the gradebook of the student's course field? Does the answer to the previous question change if we checked equality with `==`?

**Study Question:**  Does setting the student's course field to `null` change the actual `Course` object?

## Understanding Mutation

:::warning
We will cover the material for this in class on Monday 5/24.
:::

Now that you have the ability to update fields within objects, it's important to understand how changes show up in your code.

### `GradeReport` Memory Diagram

The following code creates a grade report for a course. 

```java=1
// Create new courses
Course cs18 = new Course("CSCI", 180);
Course turk = new Course ("TKSH", 100);
// Create a new student
Student isabel = new Student ("Isabel", cs18, turk);
// Create a GradeReport
// NOTE: This is not how a GradeReport is normally created
// You should actually do cs18.storeGrade(isabel, new SNCGrade("S"))
// But that would make for an overly complicated memory diagram
GradeReport grade = new GradeReport(isabel, cs18, new SNCGrade("S"));
```
**Task:** Draw the memory diagram (showing the environment and heap) that exists at the end of running this program. Upload a photo or scan of your diagram to your working directory in file a called `GradeReportMemoryDiagram.jpg`.

### Shallow and Deep Copy Memory Diagrams

The following code creates a list of grade reports. 
```java=
// Create new courses
Course cs18 = new Course("CSCI", 180);
Course turk = new Course ("TKSH", 100);
// Create new students
Student thet = new Student("Thet", cs18, turk);
Student harshini = new Student ("Harshini", cs18, turk);
// Create new grades
SNCGrade sGrade = new SNCGrade("S");
LetterGrade aGrade = new LetterGrade("A");
// Create new grade reports
// NOTE: This is not how a GradeReport is normally created
// You should actually do cs18.storeGrade(thet, sGrade)
GradeReport thetGrade = new GradeReport(thet, cs18, sGrade);
GradeReport harshGrade = new GradeReport(harshini, cs18, aGrade);
// add to list
IList list1 = new EmptyList();
list1 = list1.addFirst(thetGrade);
list1 = list1.addFirst(harshGrade);
```
:::info
In the last task, you drew all the objects that go into creating a `GradeReport` in `GradeReportMemoryDiagram.jpg`. Now, for simplicity, feel free to **omit the boxes of the `Student` and `Course` objects** when drawing the diagrams of `list1` and its copies, while knowing that it in reality would have these objects.
:::
**Task:** Draw the memory diagram (showing the heap and environment) that would exist if we called `shallowCopy` on `list1`. Upload or save an image of this diagram to your working directory in a file called `ShallowCopyLayout.jpg`.

**Task:** Draw the memory diagram (showing the heap and environment) that would exist if we called`deepCopy` on `list1`. Upload or save an image of this diagram to your working directory in a file called `DeepCopyLayout.jpg`.

### Mutation Exercises

**Task:** In the`testMutationExercisesPartOne` method in `Homework2TestSuite.java`, make a course with gradebook entries for two students. Create a test that changes the grade for that student, then lookup the same grade and make sure it has the changed value. 

**Task:** Now make another test that starts with a course with a gradebook with two students. Within the test, create a shallow copy of the gradebook. Update the grade in the original gradebook, then test the value of the grade in the shallow copy. It's up to you to figure out whether the original grade or the new grade should be in the shallow copy (and to write the expected answer for your test accordingly).

**Task:** Repeat the previous task, this time with a deep copy of the gradebook.

**Task:** Copy your shallow-copy test (two tasks ago) to the `testMutationExercisesPartTwo`. This time, after you make the copy, use `storeGrade` to record a grade for a new student. Replace the `checkExpect` with one that checks whether the new grade appears in the shallow copy (figure out whether or not it does, then write the expected output of the test accordingly).

## Reflection

The series of tests that we asked you to write in the previous section are trying to get you to think about the impacts of updating fields on the data in your programs. 

**Task:** Write responses to the following questions in `MutationQuestions.txt`
* In the sequence of tests that we asked you to write above, why did we have you create a new course in each test, rather than reuse the same course across multiple tests?
* If you modify a field in an object, which names in the environment can access the new value? If it helps, answer in terms of the structure of the memory diagram.
* Summarize the difference between a shallow copy and a deep copy of a list. Give an example of when  you would want to use each one as a programmer.
* Is the concept of a shallow copy versus a deep copy important when programming in a functional language with no side effects? Why or why not?
* Describe one thing that you have learned about the differences between programming with field updates and programming functionally (without them). We're looking for something more than "values can change" (that's just the definition); instead, talk about something that you have to pay attention to now, something you hadn't realized before, etc.

## FAQ 

**Do we have to test all the methods in the stencil?** 
No, only the ones you write. 

**What's a memory diagram?** 
You can see a memory diagram example in starting in lecture 1. [Here is a powerpoint with the diagram filled out.](https://brown-cs18-master.github.io/content/lectures/01intro/notional-machine-classes-objects.pptx) Only worry about the *environment* and *heap* quadrants.

**Why aren't my objects updating when I try to test them?**
While the code inside a *method* runs sequentially,   the test methods may be called in a random order inside the *class*. To combat this, make sure that *test methods aren't using shared objects.* Define the objects as local variables within a test method, or define a setup method to intitialize fields before every method. For example:

```java=
public class Homework2TestSuite {
    Course course;
    Student student;
    
    public void setup() {
        course = new Course(...);
        student = new Student(...);
    }
    
    public void testStudent(Tester t) {
        setup(); // initializes fields to what setup defines
        t.checkExpect(...);
    }
}
```

**Many other questions were addressed in the [Homework 1 FAQs](https://hackmd.io/vggs4xjAQhSNvHrC1WP21w#FAQ). Look there if you haven't already before asking on Ed or coming to hours.**

---
*Please let us know if you find any mistakes, inconsistencies, or confusing language in this or any other CS18 document by filling out the (mostly) [anonymous feedback form](https://cs.brown.edu/courses/cs018/feedback)!*