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 <rw/rstream.h>



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



