An immutable object cannot have its observable state changed after creation. A class with no setter functions can keep its own state stable, but immutability also depends on preventing access to mutable internal objects. section 5.4 section 5.7
Protecting an employee birthdate
A faulty Employee stores the caller’s Date pointer and returns its internal pointer. The caller can then change the birthdate both before and after construction. The corrected design stores a Date copy and returns a new copy, so both attempted changes leave the Employee unchanged. section 5.7
Check immutability by looking for these change paths:
- Remove public setters when the application requires state to remain fixed. section 5.4
- Copy mutable objects entering an immutable object instead of retaining caller-owned pointers. section 5.7
- Return copies rather than pointers into hidden mutable state. section 5.7
Listing 5.15 (Program 5.8 HiddenDate-1): Employee.h (faulty design)
#include <iostream>
#include <string>
#include "Date.h"
using namespace std;
class Employee
{
public:
Employee(long id, string name, Date *bdate)
: employee_id(id), name(name), birthdate(bdate) {}
Date *get_birthdate() const { return birthdate; }
friend ostream& operator <<(ostream& os, const Employee& emp);
private:
long employee_id;
string name;
Date *birthdate;
};
inline ostream& operator <<(ostream& os, const Employee& emp)
{
os << "Employee #" <<emp.employee_id << endl;
os << " Name: " << emp.name << endl;
os << " Birthdate: "; emp.birthdate->print(); os << endl;
return os;
}
Inspect the faulty Employee class to see how pointer aliasing defeats immutability. section 5.7























