Taking our view of a person as an actor as a starting point, we need first to establish the repertoire of possible behavior.
enum Role { Person = 0 , Student, Employer, Final };
class actor { defines the repertoire
public:
actor() { }
virtual void walk() { if (exists()) self()->walk(); }
virtual void talk() { if (exists()) self()->talk(); }
virtual void think() { if (exists()) self()->think(); }
virtual void act() { if (exists()) self()->act(); }
virtual void become(Role) { } only for a person
virtual void become(actor*) { }
virtual actor* self() { return this; } an empty self
int exists() { return self() != this; } who ami
};
Next, we may wish to refine the behavior of an actor for certain roles, such as for example the student and employer roles, which are among the many roles a person can play.
class student : public actor {
public:
void talk() { cout << "OOP" << endl; }
void think() { cout << "Z" << endl; }
};
class employer : public actor {
public:
void talk() { cout << "$$" << endl; }
void act() { cout << "business" << endl; }
};
class person : public actor {
public:
person(); to create a person
void become(Role r); to become a ...
void become(actor* p); change identity
int exists() { return role[Person] != this; }
actor* self() { return exists()?role[Person]->self():role [ role] ; }
private:
int _role;
actor* role[Final+1]; the repertoire
};
person::person() {
for (int i = Person; i <= Final ; i++ ) role[i] = this;
become( Person );
}
void person::become(actor* p) { role[Person] = p; } permanent
void person::become(Role r) {
require( Person <= r && r <= Final );
if (exists()) self()->become(r);
else {
_role = r;
if ( role [ role] == this ) {
switch (_role) {
case Person: break; nothing changes
case Student: role [ role] = new student; break;
case Employer: role [ role] = new employer; break;
case Final: role [ role] = new actor; break;
};
}
}
}
class adult_person : public person {
public:
void talk() { cout << "interesting" << endl; }
};
person p; p.talk(); empty
p.become(Student); p.talk(); OOP
p.become(Employer); p.talk(); $$
p.become(new adult_person); p.talk(); interesting
p.become(Student); p.talk(); OOP (new student)
p.become(&p); p.talk(); $$ (old role)
p.become(Person); // initial state