CSE 341 - Assignment 8 - Java Generics

Due: March 14, 10pm. You can use at most 1 late day for this assignment. (The reason for this is so that we can post a sample solution for people who want to use it to study for the final.)

8 points total, plus 2 points max extra credit.

Turnin: You should turn in three files: ArrayExample.java, GoodArrayExample.java, and ArrayListExample.java. If you do the extra credit question, also turn in a zip file with all of modified files (since there will be quite a few).

These questions use a hierarchy of classes of simple geometric objects. Here are the definitions:

Test.java is a little test class that you can run to make sure the other classes are working. For convenience, here is a zip file containing all the definitions, as well as the skeleton code for the Java questions: geometric.zip.

Running Java: You can run Java on whatever machine you want. If you don't have some other machine you prefer, you can use attu (javac Test.java to compile the program, java Test to run it).

  1. (2 points) This question is about Java arrays and the covariant typing rule. Look at the skeleton for the "main" method in this class: ArrayExample.java. Add some additional statements to the main method so that the code compiles correctly, and when it is run, it raises a java.lang.ArrayStoreException when adding the cone to geoshapes. (Adding the circle should be OK.) Here is the exception you should get:
    Exception in thread "main" java.lang.ArrayStoreException: Cone
            at ArrayExample.main(ArrayExample.java:10)
    
    Hint: look at the ArrayTest example in the lecture notes.

    Next, look at the code in GoodArrayExample.java. (This is exactly the same except for the class name.) Add statements to this code as needed, so that the code compiles correctly, and runs without error.

    If you want, you can add some statements to these "main" methods to get them to print something so that you know they are doing something, but you don't need to.

  2. (6 points) This question is about Java generics. Look at the skeleton code in ArrayListExample.java. Add additional methods total_area, total_perimeter, describe_all, and add_empties. Leave the main method untouched. Hint: some of these methods -- but not all -- should use wildcards in the type declarations.

    You should get this output when you run the code:

    Example with a list of shapes with a circle, a cone, and some empty shapes
    Circle[radius=1.0]
    Cone[radius=2.0,height=3.0]
    Circle[radius=0.0]
    Cone[radius=0.0,height=0.0]
    Rectangle[width=0.0,height=0.0]
    Sphere[radius=0.0]
    Total number of shapes: 6
    
    Example with a list of rectangles
    Rectangle[width=2.0,height=3.0]
    Rectangle[width=5.0,height=5.0]
    Total number of shapes: 2
    total area of rectangles: 31.0
    total perimeter of rectangles: 30.0
    
    Example with a list of 2d shapes with a circle and a rectangle
    Rectangle[width=10.0,height=10.0]
    Circle[radius=2.0]
    Total number of shapes: 2
    total area of flat shapes: 112.56637061435917
    
    Example list of spheres
    Sphere[radius=10.0]
    Sphere[radius=50.0]
    Sphere[radius=0.0]
    Total number of shapes: 3
    
  3. Extra credit (2 points max). If you do the extra credit part, turn in a separate copy of all of your files in a zip file called extra-credit.zip. (You'll need to touch most all of the files for the extra credit question, not just ArrayListExample.java.) Add a supersized method to each of your geometric shape interfaces and classes that returns a new geometric shape, of the same type as the receiver, that is twice as large in each dimension as the receiver. For example, supersizing a cone with radius 10 and height 4 should return a new cone with radius 20 and height 8.

    The obvious declaration for supersized in GeometricShape would be

    public GeometricShape supersized();
    
    However, we want the type of supersized for Cone to say that it returns a cone, not a geometric shape. Probably the best way to do this is to add a type parameter, for example:
    public interface GeometricShape<T extends GeometricShape> {
        public void describe();
        public T supersized();
    }
    
    Then the supersized method in Cone can be written as
        public Cone supersized() {
            return new Cone(2.0*radius, 2.0*height);
        }
    

    Another approach is to make supersized be a generic method, rather than making the interfaces and classes themselves be generic:

    public interface GeometricShape {
        public  T supersized();
    }
    
    However, this approach isn't as good, since (for example) a rectangle could return a circle in response to the supersized method and still satisfy the type declared in GeometricShape.

    Make the appropriate modifications to all of the geometric shape classes so that they implement the GeometricShape interface. Add a static method supersized_list to ArrayListExample that takes an array list of some kind of geometric shapes (for example, rectangles) and returns an array list of the same type, with the shapes supersized. The skeleton code in ArrayListExample.java includes some commented-out lines at the end that use a supersized_list method. Uncomment these (but don't otherwise change them). You should get the following additional output:

    supersizing a list of rectangles
    Rectangle[width=4.0,height=6.0]
    Rectangle[width=10.0,height=10.0]
    Total number of shapes: 2
    
    supersizing a list of spheres
    Sphere[radius=20.0]
    Sphere[radius=100.0]
    Sphere[radius=0.0]
    Total number of shapes: 3
    
    Kind of a lot of work for 2 points, but you should learn something useful doing it ....