CPE 102

Winter 2008

Program 3

 

Due Date

 

You must turn in a functionally correct program to receive any credit.  The grade you receive will be based on when you turn it in minus any deductions for the quality of your implementation and/or multiple submissions.  There is no deduction for the first submission and a 5% deduction for each additional submission, if any.  Programs will be checked for correctness once a day and you will be notified by email if your submission is not functionally correct.  Programs will be graded after the last due date and the results will be emailed to you within a few days of that date.

 

100% (minus any deductions) by 9:00pm Monday, 1/28/08

90% (minus any deductions) by 9:00pm Tuesday, 1/29/08

80% (minus any deductions) by 9:00pm Wednesday, 1/30/08

70% (minus any deductions) by 9:00pm Thursday, 1/31/08

 

You must also turn in a UML Diagram for the program in lecture on Monday 1/28no late diagrams accepted.  The diagram is worth 10% of your program grade and may be hand-drawn.    

                               

Errata:

 

None

 

Objectives

 

  1. To become familiar with Java inheritance.
  2. To compare and contrast the features inheritance and interfaces.
  3. To become familiar with abstract classes.
  4. To learn the difference between deep and shallow copies of objects.
  5. To learn how to properly overriding the equals() method of the Object class.
  6. More exposure to the concept of polymorphism.

 

Resources

 

  1. Java Standard API
  2. P3TestDriver.java to be published Monday 1/28.
  3. P3UnitTests.zip
  4. UML Overview

 

Orientation

  1. You will be modifying your Program 2 implementation to take advantage of your new-found skills with Java inheritance.  Now that you know about inheritance you realize there is a better way to implement your solution to Program 2.  Much of the code and instance variables defined in the various classes that implement the Shape interface turned out to be identical.  You now realize that using inheritance would allow you to avoid duplicating this code and data.  In addition to this redesign, and the code modifications it requires, you will be adding some additional features.  You will be implementing the Comparable interface so that you can order shapes bases on their type and area and implementing a new shape, Square, that will require very little new code due to inheritance and its close geometric relationship with rectangles.
  2. In addition to taking advantage of inheritance you also realized that your implementation for Program 2 was vulnerable to having the instance variables of your class being modified by code outside the class.  This is because you did not make deep copies of all mutable objects being passed in and/or out of the classes via constructors and methods.  You will fix this vulnerability in Program 3.
  3. JUnit tests will be provided in P3UnitTests.zip.  A stubbed out version of RectangleTest.java is given. You can replace this with your completed version from Program 2 but then be sure to modify your existing RectangleTest.java JUnit code to test for deep copies. SquareTest.java is given as an incomplete stub.  You will need to write JUnit tests for the methods you write in SquareTest.java. Use the JUnit tests for other shapes as references to write the test code.  Lastly, a new method is introduced in the AbstractShape class which is called compareTo().  You will need to write a JUnit test to test this method in the WorkspaceTest.java file.  As a recap:
    1. Modify RectangleTest.java to test for deep copies
    2. Write JUnit tests for SquareTest.java
    3. Write the testCompareTo() method in WorkspaceTest.java

 

Specification

 

  1. You MUST implement the classes and methods exactly as described.  Where exact specifications are not given you are expected to meet the spirit of the specification as given.  Ask you instructor for clarifications as necessary, the earlier the better!

 

  1. Using the javadoc-style, document all public methods in the WorkSpace class and all public methods of the Square class including those documented in the Shape interface but having different behavior from that specified in the Shape interfaces.

 

  1. All classes must make deep copies of any mutable (changeable) objects being used as instance variables coming in or going out of the class.  This includes the constructors and/or methods of the classes.  This means no other code will ever have a reference to any instance variables of any of your classes.

 

  1. Implement a Java abstract class called AbstractShape as follows:
    1. Implements the Shape interface.
    2. Has a single constructor that accepts one parameter for each of the instance variables of the class (see 4.d below).
    3. Implements only the methods in Shape that have common behavior in all of the subclasses, Circle, Rectangle, Triangle, ConvexPolygon, and Square (a new shape to be implemented in this program).
    4. Defines the instance variables that are common to all of the subclasses.
    5. Implements the Comparable interface so that its compareTo method indicates that object-A is less than object-B when A’s class name is less that B’s or, if A and B are the same class, when A’s area is less than B’s area; indicates A and B are equal when they are the same class and have the same area (+/- 0.0001); and indicates A is greater than B when A’s class name is greater than B’s or, if A and B are the same class, when A’s area is greater than B’s area.  You can use the following code to obtain any object’s name:

 

String className = yourObjectRef.getClass().getName();

 

    1. Notice that the name is a String and there may be methods of the String class that will help you compare the class names (see the Java Standard API).
    2. Override the equals() method of the Object class so that it returns true if the two objects being compared are the same class, not null, and have equal values for all instance variables.

 

  1. Modify Circle so that it extends AbstractShape rather than implements the Shape interface. 
    1. Implement only the methods that must be implemented in the Circle class and inherits the others from AbstractShape. 
    2. Implement only the instance variables that must be implemented in the Circle class and inherits the others from AbstractShape.
    3. Override the equals() method of the Object class so that it returns true when the objects being compared are both the same type, are not equal to null, and all of their instance variables, defined here and in any super classes, have equal values for all instance variables.

  1. Modify Rectangle so that it extends AbstractShape rather than implements the Shape interface. 
    1. Implement only the methods that must be implemented in the Rectangle class and inherits the others from AbstractShape. 
    2. Implement only the instance variables that must be implemented in the Rectangle class and inherits the others from AbstractShape.
    3. Override the equals() method of the Object class so that it returns true when the objects being compared are both the same type, are not equal to null, and all of their instance variables, defined here and in any super classes, have equal values for all instance variables.
    4. Modify your JUnit code to test for deep copies.

 

  1. Modify Triangle so that it extends ConvexPolygon rather than implements the Shape interface. 
    1. Implement only the methods that must be implemented in the Triangle class and inherits the others from ConvexPolygon
    2. Implement only the instance variables that must be implemented in the Triangle class and inherits the others from ConvexPolygon.
    3. Override any methods inherited from ConvexPolygon only as necessary.
    4. Note: When calling the super constructor of ConvexPolygon in Triangle's constructor you will have to constuct an array of points in the super call using array initialization syntax.  That syntax is not obvious, so here is an example for you to use:

    5.     super(new Point[] {a, b, c}, et cetera...);

      This assumes that Point references called a, b, and c have been passed as parameters to the Triangle constructor - change the names as necessary in your implementation.

 

  1. Modify ConvexPolygon so that it extends AbstractShape rather than implements the Shape interface.
    1. Implement only the methods that must be implemented in the ConvexPolygon class and inherits the others from AbstractShape. 
    2. Implement only the instance variables that must be implemented in the ConvexPolygon class and inherits the others from AbstractShape.
    3. Override the equals() method of the Object class so that it returns true when the objects being compared are same type, are not equal to null, and all of their instance variables, defined here and in any super classes, have equal values for all instance variables.

 

  1. Implement a class called Square so that it extends the Rectangle as follows:
    1. Square(double size, java.awt.Point position, Color color, boolean filled) – Constructor.
    2. Since a square is, geometrically speaking, a rectangle, the Square class should have no explicit instance variables and will, instead, make use of its super-class’s instance variables.
    3. Override any methods inherited from Rectangle only as necessary.
    4. Implement unit tests in SquareTest.java to test the Square class.

 

  1. The WorkSpace methods should have identical behavior to their Program 2 behavior.  Some of its methods will require some modification because of the use of inheritance.  Because Square is a subclass of Rectangle you will need to modify the code in the getRectangles method so that it does not return Square objects too.  The same is true for getConvexPolygons since the Triangle class is now a subclass of ConvexPolygon.  While one could make an argument that squares are rectangles and triangles are convex polygons it is a useful exercise for you to learn how to be more class specific when dealing with classes that make use of inheritance.
    1. Implement AbstractShape's testCompareTo() method in WorkspaceTest.java

  

Suggestions

  

  1. Be sure your Program 2 code passes its test driver (provided last week) before beginning Program 3.  Ask you instructor for help if you are not sure how to resolve any remaining issues.  Remember – you may not collaborate on programs.

 

  1. Create a NEW project in your IDE for Program 3 and make separate physical copies of your Program 2 files for it rather than modifying you Program 2 code directly.  You may want your original Program 2 source as a reference.  Different IDEs have unique subtleties for adding existing source to a new project – make sure you understand the subtleties of your chosen development environment.  If you are not sure about how you IDE works, ask a trusted friend, your instructor, or experiment with unimportant code until you know what you are doing.

 

  1. Develop incrementally – this means implement AbstractShape and use it to extend one of your shapes and test that code well before moving on to the other shapes.  This way you will avoid repeating the same mistakes in each shape.

 

  1. Implement the new shape, Square, after you have successfully modified your existing shapes – especially Rectangle.

  1. Keep track of your hours worked as you go, so you don’t have to guess when you hand in your assignment (see handin section below for information on time.txt).

Testing With the Provided Tests

 

  1. Your code must be 100% correct to recieve credit.  Correctness will be determined by running the acceptance test P3TestDriver.java to be published Monday 1/28.  
  2. In addition to the acceptance test, sections 7 and 9 will be graded on the quality of JUnit tests they create for this program, section 3 will not.
  3. Use the JUnit tests while developing in a test-driven approach to ensure your code's correctness before the acceptance test is released.  Run them by opening the AllTests.java file and executing it.
  4. Ask your instructor for assistance if you are not able to run these tests on your own.

Handing in Your Source Electronically…

 

  1. Create a plain text file called time.txt to log the amount of time spent on the assignment.  The file will contain only three lines with the following information on each line: name, project number, hours spent.

Example time.txt file:

 

    Sally Student

    Program 1

    7.5 hours


  1. Move the necessary file(s) to your vogon account using your favorite FTP client program.

 

  1. Log on to vogon using your favorite Shell client program.

 

  1. Change directory (cd-command) to the directory containing the file(s) to hand in.  Be sure you code compiles and runs correctly on hornet before turning it in!

 

  1. Use the following handin command being sure to replace the x with the correct maximum score you can earn based on the due date, i.e., replace x with 100 if you are handing in by Monday’s deadline, 90 for Tuesday, 80 for Wednesday, or 70 for Thursday, for example Program3-100, Program3-90, et cetera.

 

12:01pm vogon ~$ handin graderkm Program3-x Shape.java AbstractShape.java Circle.java Rectangle.java Triangle.java ConvexPolygon.java Square.java WorkSpace.java RectangleTest.java SquareTest.java WorkspaceTest.java time.txt