HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppModerate

Type-safe Date class with total encapsulation

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
totalwithencapsulationdatetypesafeclass

Problem

I want to teach about "encapsulation" and chose Date with Year, Month and Day as an example -- because it demonstrates type-safety w.r.t. preventing accidental swapping of parameters. I want to demonstrate encapusulation to the extreme, meaning I want to hide the int-values of the Year, Month and Day completely and instead define the operations in them as required.

Disregarding if it's good to go to this extreme when encapsulating, does anyone have any comments about my demonstration code?

Intro section

// #!cpp filename=33a-dateplus.cpp
#include 
#include 
using std::ostream; using std::setfill; using std::setw;


Helper value classes

Helper value class Year

class Year {
    int value_; // eg. 2014
public:
    explicit Year(int v) : value_{v} {}
    Year& operator+=(const Year& other) {
        value_ += other.value_;
        return *this;
    }
    friend ostream& operator<<(ostream& os, const Year&x) {
        return os << setfill('0') << setw(4) << x.value_;
    }
    bool isLeap() const;
};


Helper value class Month

class Day;
class Month {
    int value_; // 1..12
public:
    // v may be invalid month-number, to be normalized later, but >0 .
    explicit Month(int v) : value_{v} {}
    Month& operator+=(const Month& other) {
        value_ += other.value_;
        return *this;
    }
    friend ostream& operator<<(ostream& os, const Month&x) {
        return os << setfill('0') << setw(2) << x.value_;
    }
    void normalize(Year &year);
    // precond: month must be normalized; value_ in [1..12]
    Day days(const Year& inYear) const;
    friend bool operator<(const Month &l, const Month& r) {
        return l.value_ < r.value_;
    }
};


Helper value class Day

```
class Day {
int value_; // 1..31
public:
// v may be invalid day-of-month, to be normalized later, but >0 .
explicit Day(int v) : value_{v} {}
Day& operator+=(const Day& other) {
value_ += other.value_;
return *this

Solution

I have recently earned my M.Sc. in Comp.Sci. and one of the things that was my main gripes with any examples given to use during programming classes was the lack of consistency. So I'll say this, please be consistent and if you implement one arithmetic or relational operator you need to implement all of them that make sense.

And show them how to implement arithmetic and relational operators properly, some thing like this:

T operatpr -()  const{
    T(*this) t;
    ...
    return t;
}

T operator += (const T& rhs){
   ...
   return *this;
}

T operator + (const T& rhs) const{
   return T(*this) += rhs;
}

T operator -= (const T& rhs){
    return *this += (-rhs); 
}

T operator - (const T& rhs) const{
    return *this + (-rhs);
}

bool operator  (const T& rhs) const{
    return rhs  rhs);
}

bool operator >= (const T& rhs) const{
    return !(*this < rhs);
}

Code Snippets

T operatpr -()  const{
    T(*this) t;
    ...
    return t;
}

T operator += (const T& rhs){
   ...
   return *this;
}

T operator + (const T& rhs) const{
   return T(*this) += rhs;
}

T operator -= (const T& rhs){
    return *this += (-rhs); 
}

T operator - (const T& rhs) const{
    return *this + (-rhs);
}

bool operator < (const T& rhs) const{
    return ...;
}

bool operator > (const T& rhs) const{
    return rhs < *this;
}

bool operator <= (const T& rhs) const{
    return !(*this > rhs);
}

bool operator >= (const T& rhs) const{
    return !(*this < rhs);
}

Context

StackExchange Code Review Q#44505, answer score: 11

Revisions (0)

No revisions yet.