EECS1030Z Test 4

Thursday March 18, 2015, 14:30-15:45
Lab 01
Version G


package test4;

/**
 * A rectangle shape that can be scaled in size. A rectangle is a composition of
 * a Point2D object that stores the coordinates of the upper-right
 * corner of this rectangle.
 * 
 * The bounding box of this rectangle is the rectangular box formed by the
 * bottom-left corner of this rectangle (the Shape's position) and
 * the upper-right corner of this rectangle.
 * 
 * @author EECS1030_2014_15W
 * 
 */
public class ScalableRectangle extends ScalableShape {
  private Point2D oppCorner;

  /**
   * Create a scalable rectangle whose coordinates of the lower-left corner are
   * given by position and the upper-right corner are given by
   * oppCorner.
   * 
   * @param position
   *          the coordinates of the lower-left corner of this rectangle
   * @param oppCorner
   *          the coordinates of the upper-right corner of this rectangle
   * @pre. position.getX() < oppCorner.getX() && position.getY() < oppCorner.getY()
   * 
   */
  public ScalableRectangle(Point2D position, Point2D oppCorner) {
    super(position);
    this.oppCorner = new Point2D(oppCorner);
  }

  /**
   * Get the coordinates of the upper-corner of this rectangle. The coordinates
   * of the upper-corner of this rectangle cannot be changed using the
   * Point2D object returned by this method.
   * 
   * @return the coordinates of the upper-corner of this rectangle
   */
  public Point2D getOppositeCorner() {
    return new Point2D(this.oppCorner);
  }

  /**
   * Get the width of this rectangle. The width of the rectangle is equal to the
   * x coordinate of the upper-right corner minus the x coordinate of the
   * lower-left corner.
   * 
   * @return the width of this rectangle
   */
  public double getWidth() {
    return this.oppCorner.getX() - this.getPosition().getX();
  }

  /**
   * Get the height of this rectangle. The height of the rectangle is equal to
   * the y coordinate of the upper-right corner minus the y coordinate of the
   * lower-left corner.
   * 
   * @return the height of this rectangle
   */
  public double getHeight() {
    return this.oppCorner.getY() - this.getPosition().getY();
  }

  /**
   * Move the rectangle by an amount deltaX in the x direction and
   * an amount deltaY in the y direction. The size of the shape
   * does not change.
   * 
   * The rectangle is moved by moving both its lower-left corner and its
   * upper-right corner.
   * 
   * @param deltaX
   *          the amount to move this rectangle in the x direction
   * @param deltaY
   *          the amount to move this rectangle in the y direction
   */
  @Override
  public void move(double deltaX, double deltaY) {
    super.move(deltaX, deltaY);
    this.oppCorner.setX(this.oppCorner.getX() + deltaX);
    this.oppCorner.setY(this.oppCorner.getY() + deltaY);
  }

  /**
   * Scale the size of this rectangle by the given factor. The
   * width and height of the rectangle change by the given factor.
   * If factor > 1 then the size of the shape increases. If
   * factor < 1 then the size of the shape decreases.
   * 
   * After scaling, the position of this rectangle (its bottom-left corner) does
   * not change.
   * 
   * @param factor
   *          the factor by which to multiply the width and height of this
   *          rectangle
   * @pre. factor > 0
   */
  @Override
  public void scale(double factor) {
    Point2D p = this.getPosition();
    this.move(-p.getX(), -p.getY());
    this.oppCorner.setX(this.getWidth() * factor);
    this.oppCorner.setY(this.getHeight() * factor);
    this.move(p.getX(), p.getY());
  }

  /**
   * Draw this rectangle on the StdDraw instance using the color Color.BLACK.
   * 
   * This method first draws a filled rectangle on the StdDraw instance. This
   * method then draws a filled X in Color.BLUE marking the
   * position of the shape.
   * 
   * @see test4.Shape#draw()
   */
  @Override
  public void draw() {
    StdDraw.setPenColor(StdDraw.BLACK);
    StdDraw.filledRectangle(this.getPosition(), this.getOppositeCorner());
    super.draw();
  }
}

Other questions

Question 1

What is a possibly significant disadvantage of using composition over aggregation? (Be concise in your answer; it must be 80 characters or shorter in length)

Type your answer here: Composition requires time and memory to construct the required defensive copies.

Question 2

Suppose that a method has a parameter named y. Choose the strongest precondition on the value of y from the following choices:

A. @pre. none
B. @pre. y > 0
C. @pre. y > 100
D. @pre. y != 0

Question 3

A student extends the class test4.ScalableRectangle to create a child class lab4.BetterScalableRectangle. They override the method scale and remove the precondition that came from the parent class version of the method (i.e., they remove the precondition that @pre. factor > 0).

Has the student done anything wrong? Explain your answer with regards to removing the precondition.


No, by removing the precondition that came from the parent class version of the method, the precondition on the overridden version is now weaker than that of the parent version. Weakening the precondition of the overridden version of the method is allowed.