0

My assignment is to complete the Date class shown below. The Date class encapsulates a date by storing the month, day, and year in private instance variables.

  public class Date
  {
  // declare your instance variables here
  // postcondition: instance variables are initialized with any valid values
  // you choose
  public Date ()
  {

  }
  // postcondition: instance variables are initialized with the given values if they are valid
  // the month instance variable should be between 1-12
  // the day instance variable should be between 1-31
  // if the parameters are not valid, the instance variables are given different values that are valid
  public Date(int theMonth, int theDay, int theYear)
  {
  }
  // postcondition: returns a String in the form month/day/year
  public String toString()
  {
  }
}

The code below is what I have so far. Frankly, I am pretty confused about what I am supposed to do, and I don't have an instructor to ask. The output is " 2/2/0 "

EDIT UPDATE: If I enter a year that is invalid, such as 200, it does not print the error message... My intention with the if statement was to catch errors where the year is not 4 digits. Is this correct? Thank you for any and all help!

public class Date
{
// declare your instance variables here
private int myMonth;
private int myDay; 
private int myYear;
// postcondition: instance variables are initialized with any valid values

// you choose
public Date ()
{
    myMonth = 11;
    myDay = 11;
    myYear = 2011;
}
// postcondition: instance variables are initialized with the given values if they are valid
// the month instance variable should be between 1-12
// the day instance variable should be between 1-31
// if the parameters are not valid, the instance variables are given different values that are valid
public Date(int theMonth, int theDay, int theYear)
{
   if ( theMonth >= 1 && theMonth <= 12 ) {
       myMonth = theMonth;
   }
   else {
       System.out.print("Month Value invalid; default to 1");
       myMonth = 1;
   }
   if( theDay >= 1 && theDay <= 31 ) {
       myDay = theDay;
   }
   else {
       System.out.print("Day Value invalid; default to 1");
       myDay = 1;
   }
   if( theYear < 4 ) {
       System.out.print("Year Value invalid; default to 2000");
       myYear = 2000;
   }
   else {
   myYear = theYear;
   }
}
   // postcondition: returns a String in the form month/day/year
public String toString()
{
    return myMonth + "/" + myDay + "/" + myYear;
}

public static void main(String [] args)
{
    int theMonth, theDay, theYear;
    theMonth = 2;
    theDay = 2;
    theYear = 200;
    Date date = new Date(theMonth, theDay, theYear);
    date.toString();
    System.out.println(date);
}
}
Renea S.
  • 91
  • 1
  • 11
  • 2
    You never set `myYear` value to `theYear` value in your constructor if it's `>= 4`. It should be `if( theYear < 4 ) { System.out.print("Year Value invalid; default to 2000"); myYear = 2000; } else { myYear = theYear; }` – Alexis C. Dec 13 '13 at 20:42
  • 1
    The post-condition requirements do not call for the year to be validated at all, so you do not need to check if it's four digits or more. – Sergey Kalinichenko Dec 13 '13 at 21:19

2 Answers2

3

You need to fix your implementation in several places:

  • Since you are learning about encapsulation, you should declare your variables private
  • Assuming that there are no other methods in your class, you should also declare your variables final
  • There is no rule asking to validate the year, so the if condition needs to go; assignment of the year needs to be unconditional

This should fix the problem with printing zero instead of the year.

Note: (skip this if you have not studied exceptions yet) a common way to deal with ensuring post-conditions in the constructor is throwing exceptions when the parameters are invalid, rather than trying to guess what these parameters should have been. Consider throwing IllegalArgumentException when you detect that one of the arguments is not valid:

public Date(int theMonth, int theDay, int theYear)
{
   if ( theMonth < 1 || theMonth > 12 ) {
       throw new IllegalArgumentException("month");
   }
   if( theDay < 1 || theDay > 31 ) {
       throw new IllegalArgumentException("day");
   }
   myMonth = theMonth;
   myDay = theDay;
   myYear = theYear;
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Chances are Renea is not yet at the point where they are learning about Exceptions and standard practice. The assignment most likely requires them to set default values, so I wouldn't worry about that for now. – Mumbleskates Dec 13 '13 at 20:50
  • @Widdershins That's a fair observation, I added a note saying that OP should ignore the note about exceptions if they have not studied the topic yet. – Sergey Kalinichenko Dec 13 '13 at 20:53
1

Keep in mind! When you call date.toString(); you aren't converting the entire date variable into a String; since that doesn't actually change anything in the object, that line does nothing.

Fortunately it still works since when you call println(date) with the PrintStream object System.out, you are actually calling the variation of println() that takes an Object as a parameter instead of the one that takes a String, and what that does is get the result of the parameter's toString() method and prints that. So, it's the exact same result in the end.

The real problem is in your constructor method. Look really closely, and read through it. Pretend you are the parameter theYear and your value is 2222. At what point are you going to be used, and how?


spoilers below, seriously go look


You are in fact never setting the field myYear to anything unless the parameter theYear is invalid! The best solution here would be to add that missing else clause after you check theYear to match up with your handling of the rest of the parameters.

Mumbleskates
  • 1,248
  • 10
  • 18
  • Thank you! Your description of what is happening with the PrintStream was very informative. I have added that else statement now, so that is fixed :) But if I enter a year that is invalid, such as 200, it does not print the error message... My intention with the if statement was to catch errors where the year is not 4 digits. Is this correct? – Renea S. Dec 13 '13 at 21:03
  • @ReneaS. Ah! Actually what you are doing is checking to see if the year is less than 4. As in, the actual number 4. If it were 5 it would feel the year is absolutely fine, but if it were 2 or -394 it would replace it. What you want to test is if `theYear` is a 4 digit number... that is, any number between 1000 and 9999. So, just replace `theYear < 4` with `theYear < 1000 || theYear > 9999`, or whatever range you desire. – Mumbleskates Dec 13 '13 at 21:11
  • okay! Could you explain a little but why you used OR instead of AND? – Renea S. Dec 13 '13 at 22:18
  • @ReneaS. You are testing to see if the year is _invalid_ with this `if` statement. You want it to set it to a default value if `theYear` is too small OR it is too large; if you put `&&` there, it would always accept the value because it cannot be too large AND too small at the same time. – Mumbleskates Dec 13 '13 at 22:42
  • I see now, thanks! So theYear > 1000 && theYear < 9999 would test to see if it was valid then? And I should change the other statements also since my directions were to check if invalid, right? – Renea S. Dec 13 '13 at 22:59
  • The reverse of `theYear < 1000 || theYear > 9999` is actually `theYear >= 1000 && theYear <= 9999`. Remember, the inverse of `<` is `>=` not `>`! And it's always good to double-check your conditions. Some good advice: If you are going to have an `if` statement for every parameter, make sure that you are checking for either a **good** or a **bad** value *the same* for all your parameters. Nothing is more confusing than seeing 3 checks for `if (condition) /*invalid*/; else /*valid*/;` followed by the opposite `if (condition) /*valid*/; else /*invalid*/;`. Organize your thoughts and be consistent – Mumbleskates Dec 13 '13 at 23:08