OOP Lab 2 Exercises: Objects and Classes

Author: Ewan Klein and Joshua Ritterman
Version: 1.1
Date: 2009-01-27

Contents

Reading

Before trying the exercises, please read Chapters 2 and 3 of the textbook Head First Java.

Before submitting your answers to the Web-CAT system (available at http://demos.inf.ed.ac.uk:9000/Web-CAT), please read the document Using Web-CAT.

Exercises

Exercise 1: Walking the Dog

In this exercise, we are going to have two classes, Dog and DogOwner. A dog needs to be take for a walk if it had a drink more than 4 hours ago. The file Dog.java, shown below, has three methods: setDrinkTime(int), which allows the time of drinking to be specified as an integer; getDrinkTime(), which returns the time of drinking; and needsToGo(), which is true if the dog needs to be taken for a walk. (NB For more discussion of 'Setters' and 'Getters', see HFJ p.79.)

/**
 * TODO: Add a description of the class.
 * 
 */
public class Dog {

        // TODO: declare an instance variable to hold the drinking time

	public void setDrinkTime(int time) {
		// TODO: implement method stub
	}

	public int getDrinkTime() {
		// TODO: implement method stub
	}

	/**
	 * The dog needs to go for a walk if it had a drink more than 4 hours ago;
	 * i.e., if getDrinkTime() returns a value > 4.
	 */
	public boolean needsToGo() {
		// TODO: implement method stub
	}
}

Your first task is to implement these methods. In order to do this, you will also have to create an instance variable which stores the time of drinking.

Now have a look at DogOwner.java:

/**
 * TODO: Add a description of the class.
 * 
 */
public class DogOwner {
		
	/**
	 * Take the dog for a walk if it needs to go.
	 * @param d    The dog that needs walking.
	 * @return     Whether or not to take the dog for a walk.
	 */
	public boolean takeForWalk(Dog d) {
		// TODO: implement method stub
	}
}

Here, you need to implement the takeForWalk(Dog d) method, which returns the value true if d needs to go, and false otherwise.

In order to test the interaction between the two classes, it's helpful to have a 'TestDrive' class with a main() method, as suggested in HFJ p.36. We're going to refer to this as a 'Launcher'. Here's an example, called DogWalkLauncher.java:

/**
 * Test the interaction between a DogOwner and a Dog.
 * 
 */
public class DogWalkLauncher {

	public static void main(String[] args) {
		DogOwner owner = new DogOwner();
		Dog dog1 = new Dog();
		Dog dog2 = new Dog();

		boolean testDogWalk1 = false;
		boolean testDogWalk2 = false;

		// Specify when the dogs last drank.
		dog1.setDrinkTime(2);
		dog2.setDrinkTime(5);

		// Test the negation of a condition.
		if (!owner.takeForWalk(dog1)) {
			testDogWalk1 = true;
		}

		if (owner.takeForWalk(dog2)) {
			testDogWalk2 = true;
		}

		System.out.println("testDogWalk1: " + testDogWalk1);
		System.out.println("testDogWalk2: " + testDogWalk2);
	}
}

If you have implemented the methods in Dog and DogOwner correctly, and compiled all your source files, the command:

% java DogWalkLauncher

should print the following lines to the terminal:

testDogWalk1: true
testDogWalk2: true

When you are satisfied that you have got everything working, create a zip archive of your files Dog.java and DogOwner.java (it doesn't matter what you call this zip archive) and submit it to the assignment Lab 2.1: Walking the Dog on Web-CAT. Web-CAT will run a test over your files, similar to DogWalkLauncher and let you know how you got on.

Sample solutions

Dog.java:

public class Dog {
	
	int drinkTime = 0;
	
	public void setDrinkTime(int time) {
		drinkTime = time;
	}
	
	public int getDrinkTime() {
		return drinkTime;
	}
	
	public boolean needsToGo() {
		if (getDrinkTime() > 4) {
			return true;
		}
		return false;
	}

}

DogOwner.java:

package week02;

public class DogOwner {
		
	/**
	 * Does the dog need taking for a walk?
	 * @param d  The dog that needs walking.
	 * @return	 Whether or not to take the dog for a walk.
	 */
	public boolean takeForWalk(Dog d) {
		if (d.needsToGo()) {
			return true;
		}
		return false;
	}
}

Exercise 2: The Movie Reviewer, Version 1

In this exercise, we are going to create class Reviewer1 to model someone who assigns ratings (1 to 5 stars) movies. First off, how are we going to specify the movies and their ratings? A first thought might be to to create an array of strings, each element of which is the title of a movie, along the following lines:

String[] movies = {"The Matrix", "ET", "Slumdog Millionaire",
                  "Le Rayon Vert", "Mamma Mia"};

However, we then have the problem of associating ratings with these strings. Let's be really simple-minded, and assume instead that ratings are represented as an array of ints (with values in the range 1--5), and that we know which position in the array corresponds to which movie; i.e., we interpret the array {3, 4, 5, 2, 1} as meaning that the movie corresponing to 0th element (say "The Matrix") gets rating 3. In order to see how this class works, take a look first at Reviewer1Launcher.java:

/**
 * Test the The Reviewer1 class.
 */
public class Reviewer1Launcher {

	public static void main(String[] args) {

		boolean testGetRating1 = false;
		boolean testFavourite = false;
		
/**   This array is just an example of some movies --
 *    it doesn't actually get used.
 *
 *    String[] movies = {"The Matrix", "ET", "Slumdog Millionaire",
 *			"Le Rayon Vert", "Mamma Mia"};
 */
		
		Reviewer1 r1 = new Reviewer1();
		
		// setRating1(i, j) -- assign the value j 
                // to the movie corresponding to index i 
		r1.setRating1(0, 3);
		r1.setRating1(1, 4);
		r1.setRating1(2, 5);
		r1.setRating1(3, 2);
		r1.setRating1(4, 1);
		
		// Run some tests.
		if (r1.getRating1(1) == 4) {
			testGetRating1 = true;
		}
		
		if (r1.favourite1() == 2) {
			testFavourite = true;
		}

		System.out.println("testGetRating1: " + testGetRating1);
		System.out.println("testFavourite: " + testFavourite);
	}
}

You can infer that a Reviewer1 object has a method setRating(int index, int rating) which allows a rating to be assigned to the movie corresponding to the position, and getRating(int index) method which returns the rating for the movie at a given index. In addition, there is a method favourite1() which returns the index of the reviewer's most highly ranked movie. Now, given the skeleton Reviewer1.java shown below, your next task is to implement each of these methods so that Reviewer1Launcher will run successfully:

/**
 * The Reviewer1 class represents a person who can rate a movie, 
 * by assigning it a score from 1 to 5.
 */
public class Reviewer1 {
	
	/**
	 * Assume there are exactly 5 films that need to be rated.
	 */
	int[] ratings = new int[5]; 


	public void setRating1(int movieIndex, int rating) {
		// TODO: implement method stub
	}

	public int getRating1(int movieIndex) {
		// TODO: implement method stub
	}
	
	/**
	 * Return the index of the film which gets the highest rating.
	 */
	public int favourite1() {
		// TODO: implement method stub
	}
}

Then submit your version of the file Reviewer1.java as your answer for assignment Lab 2.2: Movie Reviewer 1 on Web-CAT.

Sample solution

Reviewer1.java:

/**
 * The Reviewer1 class represents a person who can rate a movie, 
 * by assigning it a score from 1 to 5.
 */
public class Reviewer1 {
	
	/**
	 * Assume there are exactly 5 films that need to be rated.
	 */
	int[] ratings = new int[5]; 

	/**
	 * Set the rating for a movie.
	 * 
	 * @param movieIndex
	 *            The index that corresponds to a movie in an array
	 * @param rating
	 *            The rating of the movie
	 */
	public void setRating1(int movieIndex, int rating) {
		ratings[movieIndex] = rating;
	}

	/**
	 * Get the reviewer's rating for the movie corresponding to a given index.
	 * 
	 * @param movieIndex
	 *            Index of the movie to be rated.
	 * @return The rating for the movie.
	 */
	public int getRating1(int movieIndex) {
		return ratings[movieIndex];
	}
	
	public int favourite1() {
		int max = 0;
		int index = 0;
		
		for (int i = 0; i < ratings.length; i++) {
			if (ratings[i] > max) {
				max = ratings[i];
				index = i;
			}
		}
		return index;
	}

}

Exercise 3: The Movie Reviewer, Version 2

Obviously, it would be nicer if we could refer to the movies by title, and that's what we will do in Reviewer2. Here's Reviewer2Launcher.java:

/**
 * Test the Reviewer2 class.
 * Movies can be referred to by their title
 */
public class Reviewer2Launcher {

	public static void main(String[] args) {
		boolean testShowIndex = false;
		boolean testGetRating2 = false;
		boolean testFavourite2 = false;

		String[] movies = { "The Matrix", "ET", "Slumdog Millionaire",
				"Le Rayon Vert", "Mamma Mia" };

		Reviewer2 r2 = new Reviewer2();

		// Initialise the ratings.
		r2.setRating2("The Matrix", 3, movies);
		r2.setRating2("ET", 4, movies);
		r2.setRating2("Slumdog Millionaire", 5, movies);
		r2.setRating2("Le Rayon Vert", 2, movies);
		r2.setRating2("Mamma Mia", 1, movies);

		// Run some tests.

		if (r2.showIndex("ET", movies) == 1) {
			testShowIndex = true;
		}

		if (r2.getRating2("Le Rayon Vert", movies) == 2) {
			testGetRating2 = true;
		}
		
		if (r2.favourite2(movies) == "Slumdog Millionaire") {
			testFavourite2 = true;
		}

		System.out.println("testShowIndex: " + testShowIndex);
		System.out.println("testGetRating2 " + testGetRating2);
		System.out.println("testFavourite2 " + testFavourite2);

	}

}

The methods exposed by Reviewer2 are similar to before, but apart from taking the title of the movie as a parameter, they also require that the array movies is passed as a parameter. Here's the skeleton file Reviewer2.java whose methods you need to implement:

/**
 * The Reviewer2 class represents a person who can rate a movie, 
 * by assigning it a score from 1 to 5.
 */
public class Reviewer2 {

	int[] ratings = new int[5];

	/**
	 * Set the value of ratings for a particular movie.
	 */
	public void setRating2(String movie, int rating, String[] movies) {
		// TODO: implement method stub
	}

	/**
	 * Get the current rating for a movie.
	 */
	public int getRating2(String movie, String[] movies) {
		// TODO: implement method stub
	}

	/**
	 * Utility to map from a name to an index in an array.
	 * 
	 * @param movie
	 *            the title of a movie
	 * @param movies
	 *            a list of movies titles
	 * @return the index of movie in movies
	 */
	public int showIndex(String movie, String[] movies) {
		// TODO: implement method stub
	} 
	
	public String favourite2(String[] movies) {
		// TODO: implement method stub

	}
}

The crucial method is showIndex(String movie, String[] movies), which returns the index at which movie occurs in the array movies. You might want to implement this first.

Make sure your version of the class Reviewer2 works correctly with Reviewer2Launcher, then submit the source file as your answer for assignment Lab 2.3: Movie Reviewer 2 on Web-CAT.

Sample solution

Reviewer2.java:

/**
 *  The Reviewer2 class represents a person who can rate a movie, by
 *  assigning it a score from 1 to 5.
 */
public class Reviewer2 {
	String name;
	// String[] movies = new String[5];
	int[] ratings = new int[5];

	/**
	 * Set the value of ratings for a particular movie.
	 * @param movie		The name of the movie to be rated.
	 * @param rating	The rating of the movie.
	 * @param movies	A list of movies to be rated.
	 */
	public void setRating2(String movie, int rating, String[] movies) {
		int movieIndex = showIndex(movie, movies);
		ratings[movieIndex] = rating;
	}

	/**
	 * Get the current rating for a movie.
	 * @param movie		The name of the movie that we are interested in.
	 * @param movies	The list of movies which have been rated
	 * @return		The rating for the movie.
	 */
	public int getRating2(String movie, String[] movies) {
		int movieIndex = showIndex(movie, movies);
		return ratings[movieIndex];
	}

	/**
	 * Utility to map from a name to an index in an array.
	 * 
	 * @param movie
	 *            The name of movie
	 * @param movies
	 *            The list of movies
	 * @return    The index of movie in movies
	 */
	public int showIndex(String movie, String[] movies) {
		int index = 0;
		for (int i = 0; i < movies.length; i++) {
			if (movies[i] == movie) {
				index = i;
			}
		}
		return index;
	} 
	
	public String favourite2(String[] movies) {
		int max = 0;
		int index = 0;
		
		for (int i = 0; i < ratings.length; i++) {
			if (ratings[i] > max) {
				max = ratings[i];
				index = i;
			}
		}
		return movies[index];
	}
}

Exercise 4: The Movie Reviewer, Version 3

It is rather clunky to use the array of ints (i.e. the array we called ratings) as a way of storing the ratings. Can we do better? In this exercise, we introduce a new class Movie which allows us to bundle together both a title and a rating in a single object.

As before, let's start off by looking at Reviewer3Launcher.java:

/**
 * Test the Reviewer3 Class
 *
 */
public class Reviewer3Launcher {

	public static void main(String[] args) {

		boolean testFavourite3 = false;
		Movie[] movies = new Movie[5];

		// Initialise the array elements by looping through the array.
		for (int i = 0; i < movies.length; i++) {
			movies[i] = new Movie();
		}

		// Set the movie titles
		movies[0].setTitle("The Matrix");
		movies[1].setTitle("ET");
		movies[2].setTitle("Slumdog Millionaire");
		movies[3].setTitle("Le Rayon Vert");
		movies[4].setTitle("Mamma Mia");

		Reviewer3 r3 = new Reviewer3();
		// tell the Reviewer3 which movies to rate
		r3.setMovies(movies);

		// Initialise the ratings.
		r3.rateMovie("The Matrix", 3);
		r3.rateMovie("ET", 4);
		r3.rateMovie("Slumdog Millionaire", 5);
		r3.rateMovie("Le Rayon Vert", 2);
		r3.rateMovie("Mama Mia", 1);

		// Run a test.
		// There was a mistake in the Lab Exercise here.
		if (r3.favourite3() == "Slumdog Millionaire") {
			testFavourite3 = true;
		}

		System.out.println("testFavourite3: " + testFavourite3);

	}

}

Here, we start off by declaring and initialising an array of Movies. Notice now that we are taking a movie to be not just a string, but rather an object of class Movie. As before, complete the method stubs in the skeleton Reviewer3.java.

public class Reviewer3 {

	Movie[] movies;
	
	/**
	 * Allow the reviewer's movies to be set by another object.
	 */
	public void setMovies(Movie[] newmovies) {
		// TODO: implement method stub
	}

	/**
	 * Let the reviewer rate one of the movies.
	 */
	public void rateMovie(String title, int rating) {
		// TODO: implement method stub
	}

	/**
	 * Pick the reviewer's favourite movie.
	 */
	public String favourite3(Movie[] movies) {
		// TODO: implement method stub
	}
}

In addition, implement the Movie class from scratch. Make sure your Reviewer3 and Movie classes work correctly with Reviewer3Launcher, zip up the two source files, then submit the zip archive as your answer for assignment Lab 2.4: Movie Reviewer 3 on Web-CAT.

Sample solution

Reviewer3.java:

/**
<<<<<<< Reviewer3.java
 * @author Ewan Klein
 * Model of a movie reviewer.
=======
 *  The Reviewer3 class represents a person who can rate a movie, by
 *  assigning it a score from 1 to 5.
>>>>>>> 1.3
 */
public class Reviewer3 {

	private Movie[] movies;

	/**
	 * Allow the reviewer's movies to be set by another object.
	 */
	public void setMovies(Movie[] newmovies) {
		movies = newmovies;
	}

	/**
	 * Let the reviewer rate one of the movies.
	 */
	public void rateMovie(String title, int rating) {
		for (int i = 0; i < movies.length; i++) {
			if (movies[i].getTitle() == title) {
				movies[i].setRating(rating);
			}
		}
	}

	/**
	 * Pick the reviewer's favourite movie.
	 */
	public String favourite3() {
		int max = 0;
		int index = 0;

		for (int i = 0; i < movies.length; i++) {
			if (movies[i].getRating() > max) {
				max = movies[i].getRating();
				index = i;
			}
		}
		return movies[index].getTitle();
	}
}

OPTIONAL Exercise 5: A Movie Rental Inventory System

The goal of this optional exercise is to design and implement a simple inventory control system for a small video rental store. Define least two classes: a class Video to model a video and a class VideoStore to model the actual store.

Assume that an object of class Video has the following attributes:

  1. A title;
  2. a flag to say whether it is checked out or not; and
  3. an average user rating.

Add instance variables for each of these attributes to the Video class.

In addition, you will need to add methods corresponding to the following:

  1. being checked out;
  2. being returned; and
  3. receiving a rating.

The VideoStore class will contain at least an instance variable that references an array of videos (say of length 10). The VideoStore will contain the following methods:

  1. addVideo(String): add a new video (by title) to the inventory;
  2. checkOut(String): check out a video (by title);
  3. returnVideo(String): return a video to the store;
  4. receiveRating(String, int) : take a user's rating for a video; and
  5. listInventory(): list the whole inventory of videos in the store.

Finally, create a VideoStoreLauncher class with a main() method which will test the functionality of your other two classes. It should allow the following.

  1. Add 3 videos: "The Matrix", "Godfather II", "Star Wars Episode IV: A New Hope".
  2. Give several ratings to each video.
  3. Rent each video out once and return it.
  4. List the inventory after "Godfather II" has been rented out out.

Summary of design specs:

  • Store a library of videos identified by title.
  • Allow a video to indicate whether it is currently rented out.
  • Allow users to rate a video and display the percentage of users that liked the video.
  • Print the store's inventory, listing for each video:
    • its title,
    • the average rating,
    • and whether it is checked out or on the shelves.

Zip up all your source files (including the Launcher source file) and submit them as your answer for assignment Lab 2.5: Video Rental Inventory System on Web-CAT.

Sample solution

There is currently no proposed model answer for this exercise. However, it essentially amounts to the code used in Lab 3.


Date: Thu 29 Jan 2009 19:04:56 GMT

OOP Informatics Home