owned this note
owned this note
Published
Linked with GitHub
---
tags: labs, spr22
---
# Lab 2 (CS17/111/112/19): Lists, Access Modifiers, and Equals
## Learning Objectives
- Practice working with `LinkedList`
- Learn how to use access modifiers
- Learn how to design around access modifiers
- Learn about `equals` methods and how to write them
## Stencil
Using this [GitHub Classroom link](https://classroom.github.com/a/2uEuxwMq), accept the assignment and clone on your machine. See our [GitHub Guide](https://hackmd.io/jNFtrBaMQ0yx_AgKTPWyMg?view#Accepting-an-Assignment-on-GitHub-Classroom) for more detailed instructions.
## Setup
For this lab, we will work with a modified version of the `Student`, `Faculty` and `Course` classes from your homework sequence. You do **NOT** need to apply the work from lab to the homework though. This also means you will not be penalized for incorrect access modifiers in the homework.
### Problem Sequence
The stencil code gives you initial versions of our key classes, as well as a `Main` class. As we saw in Monday's lecture, `Main` is the conventional name for the class where you run your program. Here, we are going to use `Main` as a simple way to try out code and print the results.
**Task:** Grab the stencil code and run the `main` method in the `Main` class (in a week or so, we'll be able to explain all the parts of the `public static void` line -- just accept that it is needed for now). You should see a message print out that reads `"Data setup complete"`. This confirms that you are ready to start the actual lab problems.
**Task:** Draw an environment/heap diagram for the data that has been created so far. For now, draw a list in the heap as follows:

(we'll look at how lists are really drawn in the heap in class starting on Wednesday.)
:::success
**Checkpoint:** Have a TA check your work!
:::
### Practice with for loops - [Try Again, and Again, and Again...](https://www.youtube.com/watch?v=qTA0RuZoIxM)
**Task:** Write a method in the `Student` class named `tookCoursesFrom` that returns a `LinkedList<String>` of the names of all `Faculty` that taught a course in the student's `completed` list.
*There's a method already in the `Student` class named `hasCourseFrom` that takes a `Faculty` as an argument and returns a boolean indicating whether the student is currently taking a course from the given faculty member. You can use that as an example.*
**Task:** Uncomment the code in`BLOCK 1` in the `Main/main` method (and run `main`) to make sure that your code is working.
### Wrap up the Semester
At the end of the semester, the courses that a student has just finished taking should be moved to the `completed` list within the `Student` class. The `taking` list should also be emptied out so that the student can enroll in new courses.
**Task:** Write a method `endSemester` in the `Student` class that adds all classes in `taking` to the `completed` list, then resets `taking` to an empty list.
**Task:** Uncomment the code in `BLOCK 2` in the `Main/main` method (and run `main`) to make sure that your code is working.
**Task:** Adjust your environment/heap diagram to match what the data look like after `BLOCK 2` completes.
:::success
**Checkpoint:** Have a TA check your work!
:::
### Start a new semester - [New Semester, New Slang](https://youtu.be/zYwCmcB0XMw)
It's time for a new semester!
**Task:** Look at the code in `BLOCK 3`. Without writing the code, figure out (a) what we probably want the last `println` in that block to produce and (b) what you think that `println` will produce. Work with your environment/heap diagram to justify your reasoning, modifying it to show the result of running `BLOCK 3`.
**Task:** Uncomment the code in `BLOCK 3` and check your prediction. If your prediction was incorrect, look at the diagram again and try to figure out what happened and why. Try this before reading on.
:::spoiler Open here for an analysis of what happened
Having a new professor take over a course in a new semester should not change the set of profs who Pedro took courses from previously. The problem is that we have only one `Course` object that is trying to serve as both the past offering and the current offering of the `drumming` class.
:::
### Preserving old data
In a world where old data gets permanently changed, we sometimes need to save copies of older versions of data before we make changes.
**Task:** Write a method named `clone` in the `Course` class that takes no arguments but produces a new `Course` object with the same field values as the `this` object.
**Task:** Modify your `endSemester` method in the `Student` class to put copies of the courses taken into the `completed` list. Rerun the code and make sure that Pedro's list of former instructors is now unchanged from before the faculty member teaching `drumming` was changed.
**Task:** Adjust your environment/heap diagram to match what the data look like after modifying `endSemester` to make copies of `Courses`.
:::success
**Checkpoint:** Have a TA check your work!
:::
### Protecting the Faculty! - [They’re Irreplaceable](https://www.youtube.com/watch?v=2EwViQxSJJQ)
The line `drum.taughtBy = profC` in `BLOCK 3` is a bit worrisome from an OO design perspective. What if the university decides to change how it stores the connections between courses and faculty? Perhaps there won't be a `taughtBy` field in future versions, but some other data structure to store this information. Were the university to make this change, existing code would break.
To make code more reusable, many languages (including Java) have a notion of *access modifiers*, which limit which fields of an object other classes can see. Up until now, we've been annotating all methods and fields with `public`, which means all classes can read and write to those fields. The alternative annotation, `private` will prevent outside classes from seeing those fields.
**Task:** In the `Course` class, put the annotation `private` in front of `taughtBy`, as follows:
```
private Faculty taughtBy;
```
Once you do this, anywhere in the code where you try to access the `taughtBy` field from outside of the `Course` class will turn red (signaling an error). We need to rework the code to avoid this.
For example, you might have the following line in your `Student` class:
```=java
if (c.taughtBy.equals(f))
```
Rather than "pull out" `c.taughtBy` so we can work with it in the `Student` class, we make a method inside the `Course` class that does the key work. Here, we'd rewrite this code as:
```=java
if (c.isTaughtBy(f)) {...}
```
We write the new `isTaughtBy` method in `Course` and give it the faculty member to compare to. The use of `.equals` would move into that method.
**Task:** Write `isTaughtBy` as outlined above.
**Task:** Fix the use of `drum.taughtBy = profC` in the `Main` class (`BLOCK 3`) by adding a method `changeProf` to the `Course` class.
**Task:** Using these two as models, convert any remaining uses of `taughtBy` that are outside the `Course` class into methods within the `Course` class.
:::success
**Checkpoint:** Have a TA check your work!
:::
### Equality - [The Real Course Object?](https://www.youtube.com/watch?v=eJO5HU_7_1w)
Consider the following two `Courses`: should they be considered the same or not?
```
new Course("drumming", profA)
new Course("drumming", profB)
```
Whether you consider these the same depends on context. If we want to know whether a student has taken the `"drumming"` course (say, as a prereq), we probably don't care who taught it. But if you want to know whether two students took the same course at the same time, we might want these to be different.
Java lets you (the programmer) indicate when two objects from the same class should be considered the same. You do this by writing a method called `equals`. This method can choose which fields to consider when comparing two objects. Here, for example is a `.equals` method that compares `Course` objects based only on their names (it would go in the `Course` class):
```=java
@Override
public boolean equals(Object other) {
if (other instanceof Course) {
return this.nameNum.equals(((Course) other).nameNum);
} else {
return false;
}
}
```
The heart of the method is line 3, which compares the `nameNum` fields of the two objects. The rest of this contains details that Java needs. Specifically:
- the input to an `equals` method has to allow any other object (not necessarily one from the same class). The Java type `Object` allows any object.
- But if the `other` value is not a `Course`, there is no way that `other` and `this` are equal. Line 2 asks "is `other` an object from the `Course` class?"
- Once we are inside the `if` branch on line 3, we as programmers know that `other` must be a `Course` (line 2 checked that). But Java doesn't know that. The expression `((Course) other)` tells Java "I the programmer know that `other` is a `Course`, so let me access the `nameNum` field.
Every class has a default `equals` method that checks whether two objects are at the same location in the heap. You can always override that, however, with code like the above.
**Task:** Get familiar with the `equals` method, either by editing it to see what breaks (make the `Object` type into `Course`, take off the `(Course)` before `other`, etc) or by trying to add an `equals` method to the `Student` class that calls two `Student` objects equal if they have the same Student name. You could also add an `id` field to students and add that to the `equals' check.
:::success
**Checkoff!** Congratulations! Call over a TA to get credit for completing the lab!
:::
______________________________
*Please let us know if you find any mistakes, inconsistencies, or confusing language in this or any other CSCI0200 document by filling out the [anonymous feedback form](https://docs.google.com/forms/d/e/1FAIpQLSdFzM6mpDD_1tj-vS0SMYAohPAtBZ-oZZH0-TbMKv-_Bw5HeA/viewform?usp=sf_link).*