Implementing Associations by Frank Hellwig Example 1: (a) class Dog; class Person { public: void addPet(Dog* d) { pets_.add(d); } private: Vector pets_; }; class Dog { public: Dog() : master_(0) { } void setMaster(Person* p) { master_ = p; } private: Person* master_; }; (b) Person* bill = new Person(); Dog* fido = new Dog(); bill->addPet(fido); fido->setMaster(bill); (c) Dog::setMaster(Person* p) { master_ = p; master_->addPet(this); } Example 2: void Person::addPet(Dog* dog) { int ndogs = getObjects("dog").entries(); if (ndogs > 3) { cerr << "Too many dogs." << endl; return; } associateWith(dog, "dog", "person"); } Example 3: ofstream f("world"); RWbostream strm(f); strm << world; Listing One class AssociationObject : public RWCollectable { RWDECLARE_COLLECTABLE( AssociationObject) public: AssociationObject(); ~AssociationObject(); void associateWith( AssociationObject* obj, const RWCString& name, const RWCString& inverseName); void associateWithPart( AssociationObject* obj, const RWCString& name, const RWCString& inverseName); void dissociateFrom( AssociationObject* obj, const RWCString& name); void dissociate( const RWCString& name); AssociationObject* getObject( const RWCString& name) const; RWOrdered getObjects( const RWCString& name) const; RWOrdered getObjectsSorted( const RWCString& name) const; void restoreGuts(RWvistream&); void saveGuts(RWvostream&) const; }; Listing Two class AssociationRole : public RWIdentitySet { RWDECLARE_COLLECTABLE( AssociationRole) public: // Default constructor for persistence. AssociationRole() { } AssociationRole( const RWCString& inverseName, RWBoolean isAggregate); RWCString getInverseName() const { return inverseName_; } RWBoolean isAggregate() const { return isAggregate_; } void restoreGuts(RWvistream&); void saveGuts(RWvostream&) const; private: RWCString inverseName_; RWBoolean isAggregate_; }; Listing Three /* assocTest.cc */ #include "AssocObject.h" #include class World : public AssociationObject { }; class Person : public AssociationObject { public: Person(World* world) { world->associateWithPart( this, "person", "world"); } }; class Dog : public AssociationObject { public: Dog(World* world) { world->associateWithPart( this, "dog", "world"); } }; class Flea : public AssociationObject { public: Flea(Dog* dog) { dog->associateWithPart( this, "pest", "host"); } }; void main() { // Create the objects. World* world = new World(); Person* dick = new Person(world); Person* jane = new Person(world); Person* tiffany = new Person(world); Dog* spot = new Dog(world); new Flea(spot); new Flea(spot); new Flea(spot); // Create plain associations. dick->associateWith( jane, "wife", "husband"); tiffany->associateWith( dick, "parent", "child"); tiffany->associateWith( jane, "parent", "child"); tiffany->associateWith( spot, "pet", "master"); // Get Tiffany's parents. RWOrdered parents = tiffany->getObjects("parent"); // Count the fleas in the world. cout << "There are " << world->getObjects( "dog.pest").entries() << " fleas in the world." << endl; // Delete the object hierarchy. delete world; } 4