EECS1030Z Test 3

Wednesday February 25, 2015, 14:30-15:45
Lab 02
Version D


package test3;

/**
 * A class that represents time in one day using hours and minutes. The time is
 * based on a 24-hour clock: The start of each day is midnight or 0 hours and 0
 * minutes, noon is 12 hours and 0 minutes, and the end of the day is 23 hours
 * and 59 minutes.
 * 
 * <p>
 * The time represented by <code>SimpleTime</code> does not automatically change
 * with the passing of time; a client is able to manually set the time using the
 * provided mutator methods.
 * 
 * @author EECS1030_2014_15_W
 * 
 */
public class SimpleTime implements Comparable<SimpleTime> {
  
  /**
   * The hour for noon.
   */
  public static final int NOON_HOUR = 12;
  
  /**
   * The number of minutes in an hour 
   */
  public static final int MINUTES_PER_HOUR = 60;
  
  
  private int hour;
  private int minute;

  
  /**
   * Create a <code>SimpleTime</code> object that represents the same time as
   * another <code>SimpleTime</code> object.
   * 
   * @param other
   *          the <code>SimpleTime</code> object to copy
   */
  public SimpleTime(SimpleTime other) {
    this(other.getHour(), other.getMinute());
  }

  /**
   * Create a <code>SimpleTime</code> representing the time with the given hour
   * and minute.
   * 
   * @param hour
   *          the hour of the day
   * @param minute
   *          the minute of the hour
   * @throws IllegalArgumentException
   *           if <code>hour</code> is not in the range 0-23
   * @throws IllegalArgumentException
   *           if <code>minute</code> is not in the range 0-59
   */
  public SimpleTime(int hour, int minute) {
    this.setHour(hour);
    this.setMinute(minute);
  }

  /**
   * Get the hour of the day (0-23) represented by this object.
   * 
   * @return the hour
   */
  public int getHour() {
    return this.hour;
  }

  /**
   * Set the hour of the day (0-23) represented by this object.
   * 
   * @param hour
   *          the hour to set
   * @throws IllegalArgumentException
   *           if <code>hour</code> is not in the range 0-23
   */
  public void setHour(int hour) {
    if (hour < 0 || hour > 23) {
      throw new IllegalArgumentException("hour must be between 0-23");
    }
    this.hour = hour;
  }

  /**
   * Get the minute of the hour (0-59) represented by this object.
   * 
   * @return the minute
   */
  public int getMinute() {
    return minute;
  }

  /**
   * Set the minute of the hour (0-59) represented by this object.
   * 
   * @param minute
   *          the minute to set
   * @throws IllegalArgumentException
   *           if <code>minute</code> is not in the range 0-59
   */
  public void setMinute(int minute) {
    if (minute < 0 || minute > 59) {
      throw new IllegalArgumentException("minute must be between 0-59");
    }
    this.minute = minute;
  }

  /**
   * Compares this <code>SimpleTime</code> object to another
   * <code>SimpleTime</code> object.
   * 
   * <p>
   * The result is the difference in minutes between <code>this</code> time and
   * the <code>other</code> time. For example, if the time represented by
   * <code>this</code> time is 11:00 and the time represented by
   * <code>other</code> time is 13:05 then <code>this.compareTo(other)</code> returns
   * <code>-125</code>.
   * 
   * @return the difference in minutes between <code>this</code> time and the
   *         <code>other</code> time.
   */
  @Override
  public int compareTo(SimpleTime other) {
    int hour = this.getHour();
    int minutes = this.getMinute() + hour * SimpleTime.MINUTES_PER_HOUR;

    int otherHour = other.getHour();
    int otherMinutes = other.getMinute() + otherHour * SimpleTime.MINUTES_PER_HOUR;
    return minutes - otherMinutes;
  }

  
  /**
   * Returns the <code>SimpleTime</code> object equal to noon (12:00)
   * 
   * @return the <code>SimpleTime</code> object equal to noon (12:00)
   */
  public static SimpleTime noon() {
    return new SimpleTime(SimpleTime.NOON_HOUR, 0);
  }
  


  /**
   * Generate a hash code for this object.
   * 
   * @return a hash code for this object
   */
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + this.hour;
    return result;
  }

  /**
   * Compare this <code>SimpleTime</code> to an object for equality.
   * 
   * <p>
   * The result is <code>true</code> if and only if <code>obj</code> is a
   * <code>SimpleTime</code> object, and both objects represent the same time of
   * day (i.e., identical hour, minute, and AM/PM).
   * 
   * @return <code>true</code> if both <code>SimpleTime</code> objects represent
   *         the same time of day.
   */
  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (this.getClass() != obj.getClass()) {
      return false;
    }
    SimpleTime other = (SimpleTime) obj;
    if (this.hour != other.hour) {
      return false;
    }
    if (this.minute != other.minute) {
      return false;
    }
    return true;
  }

  /**
   * Returns a string representation of the time of day. The string has the
   * format <code>XX:YY</code> where <code>XX</code> is the hour of the day and
   * <code>YY</code> is the minute of the day. Both the hour and minute fields
   * are always two characters wide.
   * 
   * @return the time of day represented by this object as a string
   */
  public String toString() {
    return String.format("%2d:%02d", this.getHour(), this.getMinute());
  }
}

Other questions

Question 1

SimpleTime has 2 static int fields and 2 non-static int fields. How many int variables are used by the SimpleTime class and objects when the following main method reaches the line marked HERE?

public static void main(String[] args) {
  SimpleTime t = new SimpleTime(14, 30);
  SimpleTime u = new SimpleTime(15, 45);
  SimpleTime v = u;
  // HERE
  
  // remainder of main not shown
}
A. 4
B. 6 (2 static fields + 4 non-static fields in the two objects)
C. 8
D. 12

Question 2

Analyze the implementation of hashCode for SimpleTime; what is a weakness of the implementation?:

A. it can return different values for two SimpleTime instances that are equal
B. it can return different values when the state of the SimpleTime instance changes
C. it can return the same value for two SimpleTime instances that are not equal
D. the hashed collections will fail when using this implementation of hashCode

Question 3

You have to be very careful when adding SimpleTime references to a java.util.Set. Using one short sentence, state the reason why you have to be careful (be concise, you have a maximum of 80 characters).

Type your answer here: SimpleTime is mutable

Question 4

SimpleTime has at least two class invariants. State one of the class invariants (be concise, you have a maximum of 80 characters).

1. 0 ≤ hour < 24
2. 0 ≤ minute < 60


Question 5

Consider the following of implementation of setMinute (pseudocode is used to avoid showing you how to validate the input and throw and exception).

/**
 * Set the minute of the hour (0-59) represented by this object.
 * 
 * @param minute
 *          the minute to set
 * @throws IllegalArgumentException
 *           if minute is not in the range 0-59
 */
public void setMinute(int minute) {
  this.minute = minute;
  
  // -now validate the value of minute:
  //
  // if minute is not in the range 0-59
  //    then throw an IllegalArugmentException here
}

Assuming that the validation code is written correctly, explain whether or not this implementation of setMinute is acceptable.


This implement is not acceptable because the client can obtain a SimpleTime whose state violates the class invariants:

SimpleTime t = new SimpleTime();
try {
  t.setMinute(-1);
}
catch (IllegalArgumentException x) {
  // DO NOTHING
}
// t.getMinute() now returns -1

Question 6

Describe all of the modifications that would be required to correctly convert the SimpleTime class into a multiton class.


-add a private Map to hold the SimpleTime instances
-make the constructors private to prevent the client from creating instances
-provide a method getInstance(int hour, int minute) to allow the client to get an instance