CSE1030 Test 2R

Tue Nov 12
5:00PM - 6:20PM

Programming Question

Written Questions

Type the answers to the written questions into the file answers.txt that you were instructed to create earlier. Make sure that you number your answers to match the questions.


1. [2 marks] Does your PointMatcher implementation use aggregation or composition for its field named point? Explain why you chose aggregation or composition (no marks for guessing aggregation or composition; you must explain your answer).

The API for the method getPoint suggests that composition should have been used: "Clients cannot use this method to modify the point; clients must use setPoint to modify the point that this PointMatcher object matches."


2. Consider the following main method:

public static void main(String[] args) {

  Point2D p = new Point2D(0., 0.);
  PointMatcher m = new PointMatcher(p);

  Point2D q = m.getPoint();
  boolean b = (p == q);
  
}

(a) [1 mark] If PointMatcher used aggregation for its field named point, what is the value of the variable named b?

true, because q and position refer to the same object.

(b) [1 mark] If PointMatcher used aggregation for its field named point, how many Point2D objects are (probably) created in the main method?

1, because q and position refer to the same object.

(c) [1 mark] If PointMatcher used composition for its field named point, what is the value of the variable named b?

false, because point would be a deep copy of p

(d) [1 mark] If PointMatcher used composition for its field named point, how many Point2D objects are (probably) created in the main method?

3: p, point, and the copy created inside of getPoint


3. [2 marks] Suppose that PointMatcher used an IPoint2D to represent point instead of a Point2D. Could PointMatcher use aggregation for its point without creating a privacy leak? Explain your answer. (Recall that IPoint2D represents an immutable point.)

IPoint2D is immutable; thus, aggregation could be used without creating a privacy leak because immutable references can be shared freely.


4. Imagine that you are teaching CSE1030. You provide the students with the following utility class:

public class PointMatchers {

  // ...
  
  // Returns a new PointInSquare matcher that matches a
  // square neighbourhood that is two times the size of
  // the square used by the given matcher.

  public static PointInSquare doubleSize(PointInSquare matcher) {
    return new PointInSquare(matcher.getPoint(),
                             2. * matcher.getHalfLength());
  }

  // ...
}

One of your students shows you their code:

  // somewhere in a main method
  PointMatcher m = new PointInSquare(new Point2D(), 1.);     // A
  
  PointInSquare s = PointMatchers.doubleSize(m);                 // B
  

(a) [1 mark] The student asks you what is the declared type of m; what is your answer to the student?

PointMatcher

(b) [1 mark] The student asks you what is the run-time (or actual) type of m; what is your answer to the student?

PointInSquare

(c) [2 marks] The student asks you why is line A of the code shown correct; what is your answer to the student?

PointInSquare is a subclass of PointMatcher, and is substitutable for PointMatcher; thus, you can assign a PointInSquare reference to a PointMatcher reference.

(d) [2 marks] The student asks you why is line B of code shown incorrect; what is your answer to the student?

The method doubleSize has a PointInSquare reference as a parameter. The argument m was declared to be a PointMatcher reference, and a PointMatcher is not substitutable for a PointInSquare.


5. Suppose that you want to match all points that are inside a horizontal range as shown in the figure to the left. A point matches if it is to the left of the gray line and to the right of the blue line. You decide to create a class named PointInRange to implement this functionality, and you also choose to make it a subclass of PointMatcher.

(a) [2 marks] PointInRange requires two points to define the range: one for the gray line and one for the blue line. You decide to override setPoint so that it always sets the rightmost point (the point that defines the gray line). Your API for the overridden version of setPoint is:

  /**
   * Set the rightmost edge of the range that this PointInRange object
   * matches.
   * 
   * Precondition: p must be to the right of the left edge of the range
   *
   * @param p
   *          the point that defines the rightmost edge of the range
   */
  public void setPoint(Point2D p) {
    // implementation not shown
  }

Is the precondition acceptable? Explain your answer. (Hint: PointMatcher.setPoint has no preconditions.)

No, the precondition is not acceptable because a child class cannot strengthen the precondition of an overridden method.


(b) [2 mark] Instead of using a precondition as in part 5(a), suppose that you had decided to throw an exception instead:

  /**
   * Set the rightmost edge of the range that this PointInRange object
   * matches.
   * 
   * @param p
   *          the point that defines the rightmost edge of the range
   *
   * @throws Exception if p is not to the right of the left edge of the range
   */
  public void setPoint(Point2D p) throws Exception {
    // implementation not shown
  }

Is throwing a checked exception acceptable? Explain your answer.

No, a child class cannot throw a checked exception in an overridden method if the parent class does not throw a checked exception in the overridden method.


(c) Instead of using a precondition as in part 5(a) or throwing an exception as in part 5(b), suppose that you decide setPoint should set the point in the center of the range; you also add a new method setWidth to set the width of the range.

[2 marks] Do you need to override setPoint in PointInRange? Explain your answer.

No, setPoint in PointInRange needs to change the location of the range; this is exactly what the parent class version of setPoint already does.


[2 marks] Are you allowed to add the new method setWidth in PointInRange? Explain your answer.

Yes, a child class is allowed to add its own new methods.


(d) [3 marks] Instead of extending PointMatcher, you could choose to extend PointToLeft when implementing PointInRange. One reason for doing so is that PointToLeft already does half of the work for you by matching all points to the left of the rightmost edge of the range.

Is extending PointToLeft a good idea when implementing PointInRange? If your answer is yes, then provide one more reason why this is a good idea. If your answer is no, then explain why you think this is a bad idea.

No, this is a bad idea. PointInRange will not be substitutable for PointToLeft because PointInRange will not match any of the points to the left of its leftmost edge.

Submit

Submit your answers to the written questions and your Java program when you are finished:

submit 1030 Test2 PointMatcher.java PointLeftOf.java PointInSquare.java answers.txt