Let's say we're developing an API for other programmers. Our API has a Date object for them to use, and we want to limit what values the month, day, and year can be to valid values, such as 1-12 for the month, 1-31 for the day, and 1900-2014 for the year. So to do this, we create separate Month, Day, and Year objects, all of which are passed to Date's constructor, which we call like so:
Date date(Month::Jan(), Day(1), Year(1980));
In order to ensure that Month can only be 1-12, we can create separate functions for each month, each of which returns a month object corresponding to that month, and to ensure that no one can create a month with the wrong value, we make Month's constructor private:
class Month {
public:
static Month Jan () { return Month(1);}
static Month Feb () { return Month(2);}
static Month Mar () { return Month(3);}
static Month Apr () { return Month(4);}
static Month May () { return Month(5);}
static Month Jun () { return Month(6);}
static Month Jul () { return Month(7);}
static Month Aug () { return Month(8);}
static Month Sep () { return Month(9);}
static Month Oct () { return Month(10);}
static Month Nov () { return Month(11);}
static Month Dec () { return Month(12);}
private:
Month (int n) : monthNum (n) {}
int monthNum;
};
However, for Day and Year, we can't have function names that only contain numbers like Year::1997()
and we want this format to be intuitive to client developers, so syntaxes like Year::year1997()
are out. Plus, we don't want to manually code a function for every possible year. Let's say years go back significantly far enough that this would be a problem, like back to 1900, for instance. So we'll stick with the Day(1)
or Year(1997)
format.
Given this, what's a good way to ensure that the constructed Day and Year can only return the range of values we want? One way is to throw an exception if invalid values are entered:
class Day {
public:
Day (int d) : dayNum(d) {
if(d <= 0 || d >= 31) {
throw "Invalid day";
}
}
private:
int dayNum;
};
But this generates an error during runtime, not during compile time, and we're building this for developers to use, so we want them to know as soon as possible when they've done something wrong, such as putting an invalid day or year (e.g. day 32 or year 3000). What's an effective way to ensure clients can only create Day or Year objects with valid values, without waiting until program execution to notify them?