Java Crash Course Lab Exercises : Object Oriented Programming 1 Using Objects Case Using the Java Program Template, write a program Case that: • Checks that two arguments have been provided, and prints an error message if not • Uses the first parameter to determine if text should be converted to upper or lower case • Converts the text in the second parameter accordingly, and prints it to screen Hints: • You can use quotes to include spaces in a single command line argument: java Case upper "More than one word" (outputs, MORE THAN ONE WORD) • Lookup the String class in the Java API documentation for useful methods to convert the case of a string Address Book Using the Java Program Template, write a program Address that: • Creates a hashtable and adds several entries, where each entry is an email address keyed by a name (i.e. addresses.put("Richard", "noad@cs.bris.ac.uk"); • For each command line argument, searches the hashtable to see if there is a matching name. If there is, the name and email address should be printed out. See the API documentation for how to use the hashtable class. For example, if I populate my hashtable with (Richard, noad@cs), (Steve, steve@cs) and (Ian, ian@cs), and I run java Address Richard Ian, the output should be: Richard noad@cs Ian ian@cs 1 2 Creating Classes Rectangle 1. Make a class named Rectangle. It should have the following private fields which represent the position and size of a rectangle in 2D: • An double named xPos • An double named yPos • An double named width • An double named height It should have the following public methods: • A default constructor that initializes xPos and yPos to zero and width and height to one. • A constructor that takes two double parameters which specify values for width and height (in that order). • A constructor that takes four double parameters which specify values for xPos, yPos, width and height (in that order). • void setPos(double x, double y) • double getXPos() • double getYPos() • double getWidth() • double getHeight() • double getArea() should return width*height • String toString() should return the string "Rectangle (xPos, yPos)-(xPos+width, yPos+height)" • void printShape() should print the rectangle on the console using * characters. The double values used for position and size can be rounded into int values by casting, as in C. 2. Add a main method (public static void main(String [] args)), that... • Creates the following objects: – A default Rectangle – A Rectangle that goes from (2,2) to (4,6) • Performs System.out.println(rectangle); for both of the above objects. • Performs rectangle.printShape(); for both of the above objects. Shapes This exercise should help you to appreciate some of the fundamental principles of Object Oriented Program- ming, it involves inheritance, abstract classes and methods and overriding. Just to recap: inheritance If class B extends class A, it inherits all of the behavior of class A. It can then modify existing behavior (see overriding) or add new behavior. abstract An abstract class is one that says that it can perform a given task, but doesn’t actually implement it (this is achieved by declaring an abstract method). It is up to inheriting classes to implement the abstract methods. 2 overriding This is where a class modifies its inherited behavior. For example, public String toString() is a method in the Object class that all other classes extend, and so you can call toString() on any object. Last week, we overrode this method to return a more meaningful result than the default. The previous exercise involved creating a class to represent the concept of a Rectangle. If we wanted to create other classes to represent different shapes such as Circle, Triangle, etc, we would have to start again for each of them (we could copy-and paste, but there would still be a lot of duplicate code). Not only that, but if we wanted to store a array of these different shapes, we would have to have one array for each type of shape. Using OOP we can reduce the amount of code duplication, and make it easier to deal with each of the different shapes in more general terms. We are going to implement a simple class hierarchy, with an abstract Shape class at the top, which will be extended by Rectangle and Circle classes. 1. Make an abstract class named Shape to represent the concept of a shape. This class should be in a file named “Shape.java”. It should have the following private fields which represent the position of the shape in 2D: • An double named xPos • An double named yPos It should have the following public methods: • A default constructor that initializes xPos and yPos to zero • A constructor that takes two double parameters which specify values for xPos and yPos • void setPos(double x, double y) • double getXPos() • double getYPos() • String toString() should return the string "Shape (xPos, yPos)" These methods say that “all shapes can do this, and this is the standard way of doing it”. It should also have the following abstract public methods: • double getArea() • void printShape() These abstract methods say that “all shapes can do this, but there isn’t a general way of doing it”. 2. Use inheritance to specialize Shape into Rectangle, this class should be in a file named “Rectangle.java”. This will require two private double fields to store the width and height. The following constructors should be provided: • Rectangle() The default constructor, sets width = 1 and height = 1. • Rectangle(double width, double height) • Rectangle(double x, double y, double width, double height) This will need explicitly invoke the super-class constructor, super(x, y); You will also need to override/implement the following methods (all as per last weeks assignment): • double getArea() • void printShape() • String toString() 3 3. Use inheritance to specialize Shape into Circle, this class should be in a file named “Circle.java”. This will require a private double fields to store the radius. The following constructors should be provided: • Circle() The default constructor, sets radius = 1. • Circle(double radius) • Circle(double x, double y, double radius) This will need explicitly invoke the super-class constructor, super(x, y); You will also need to override/implement the following methods: • double getArea() should return Math.PI * radius * radius • void printShape() • String toString() should return "Circle (xPos, yPos), radius" 4. Create a class named TestShapes, in a file named “TestShapes.java”, with a main method that: • Creates the following objects: – A default Rectangle – A Rectangle that goes from (2,2) to (4,6) – A default Circle – A Circle at position (4,5) that has a radius of 3 • For each of the above shapes, System.out.println(shape); • For each of the above shapes, shape.printShape(); 3 Interfaces Collections and Interfaces This assignment will get you using collections, comparators and the online documentation! We are going to use a collection class to store a set of shapes. • The Shape class needs to be modified to implement Comparable such that the compareTo method orders shapes by area. • You program should be run by typing java TestShapes - i.e. you will require a class named TestShapes that contains your main method. • You need to select (and be able to justify) a suitable Collection class to store a number of Shape objects. • When the program is run, the user should be presented with a simple menu offering the following choices: 1. Create a new shape 2. List all shapes 3. Sort shapes 4. Exit • “Create a new shape” should present another menu offering a choice of Rectangle or Circle. The user should then be prompted to enter the appropriate shape parameters. An instance of the appropriate class should be created and stored in your collection object. 4 • “List all shapes” should iterate through your collection and print out each shape (using an iterator and System.out.println). • “Sort shapes” should present the user with the options: 1. By area 2. By position 3. Reverse current sort 4. Randomize current sort “By position” requires that the shapes should be sorted primarily by xPos and secondly (i.e. in event of equal xPos values) by yPos. • The main menu should be displayed again after completion of the selected operation (unless of course that operation was “Exit”!). Some tips to get you started: • The Collections class in the Java API contains methods for sorting, reversing and shuffling (ran- domizing) a collection object. • Sorting shapes by area is a “natural sort”, as this is the type of ordering provided by the Shape class now that it implements Comparable. • Sorting shapes by position will require you to create a Comparator class, this is simply a class that implements the Comparator interface. • Use the “EasyIn” class to read user input, it provides several convenience methods that make the task of reading integers and strings from the keyboard much easier. Available from the course webpage. 4 Object Oriented Design Text Formatting This exercise will get you thinking about how to break a problem up into manageable pieces, and also introduce you to reading input from a file. Write a program that reads the contents of a text file, and displays it on the console formatted in newspaper style columns. Your program should satisfy the follow requirements: • The name of the file to format will be the first command line argument. If this argument is missing, the program should print a suitable error message and exit. • The second command line argument specifies the number of columns, if this value is not provided it should default to 2. • The third command line argument specifies the number of rows on a “page”. If this value is not provided it should default to 20 - so once you have filled up 20 rows on the first column, you should start on the second. • The fourth command line argument specifies the width of a page. If this value is not specified it defaults to 80. 5 • The width of each column should be calculated such that each column is the same width, and the columns are spaced approximately evenly across the page. There should be a gap of at least 2 characters between each column. • Each line should be “fully justified” - this means that extra spaces are distributed along a line in order to make it fill the column. If you distribute these spaces randomly between the words it will look better than if you always start inserting at the start of the line. • If all of the columns fill up, a new page should be started. To represent this, print two blank lines before starting a new set of columns. • A new paragraph is indicated in the source text by an empty line. Paragraphs start on a new line and should be indented by an extra two spaces. • Exactly how you handle words that do not fit onto a single line is up to you. You will need to split the word into two parts, however the exact details of how you choose to do that are up to you. 5 Example The following text is in a file named “christmas carol.txt”: Marley was dead: to begin with. There is no doubt whatever about that. The register of his burial was signed by the clergyman, the clerk, the undertaker, and the chief mourner. Scrooge signed it. And Scrooge’s name was good upon ‘Change, for anything he chose to put his hand to. Running the command java ColumnFormat christmas_carol.txt should produce something similar to: Marley was dead: to begin with. There is no doubt whatever about that. The register of his burial was signed by the clergyman, the clerk, the undertaker, and the chief mourner. Scrooge signed it. And Scrooge’s name was good upon ‘Change, for anything he chose to put his hand to. Notice that as there are not yet 20 lines, the second column is empty. Running the command java ColumnFormat christmas_carol.txt 3 5 64 should produce something similar to: Marley was dead: to burial was signed by Scrooge signed it. begin with. There the clergyman, the And Scrooge’s name is no doubt whatever clerk, the was good upon about that. The undertaker, and the ‘Change, for register of his chief mourner. anything he chose to put his hand to. 6 Note how the final line has been placed at the start of a new “page”. Your output does not have to be exactly the same as the above, but it will be similar. Some tips to get you started: • The StreamTokenizer and StringTokenizer classes make the job of splitting a string up into words much easier... • When trying to think about what classes you will need, look at the nouns in the problem description (i.e. Page, Column, etc) 7