Rogue Wave Banner

Click on the banner to return to the user guide home page.

©Copyright 1996 Rogue Wave Software

Why Design an RWCollectable Class?

Before we get to the nuts and bolts of how to design an RWCollectable

class, let's discuss a concrete example of why you might choose to design RWCollectable classes.

Suppose you run a bus company. To automate part of your ridership tracking system, you want to write classes that represent a bus, its set of customers, and its set of actual passengers. In order to be a passenger, a person must be a customer. Hence, the set of customers is a superset of the set of passengers. Also, a person can physically be on the bus only once, and there is no point in putting the same person on the customer list more than once. As the developer of this system, you must make sure there are no duplicates on either list.

These duplicates can be a problem. Suppose that the program needs to be able to save and restore information about the bus and its customers. When it comes time to polymorphically save the bus, if your program na_vely iterates over the set of customers, then over the set of passengers, saving each one, any person who is both a customer and a passenger is saved twice. When the program polymorphically restores the bus, the list of passengers will not simply refer to people already on the customer list. Instead, each passenger will have a separate instantiation on both lists.

You need some way of recognizing when a person has already been polymorphically saved to the stream and, instead of saving him or her again, merely saving a reference to the previous instance.

This is the job of class RWCollectable. Objects that inherit from RWCollectable have the ability to save not only their contents, but also their relationships with other objects that inherit from RWCollectable. We call this feature isomorphic persistence. Class RWCollectable has isomorphic persistence, but more than that, it can determine at run time the type of the object to be saved or restored. We call the type of persistence provided by RWCollectable polymorphic persistence, and recognize it as a superset of isomorphic persistence.

An Example of RWCollectable Classes

The code below shows how we might declare the classes described in the previous section. Later we'll use the macro RWDECLARE_COLLECTABLE and discuss our function choices. You'll find the complete code from which this example is taken at the end of this chapter; it is also given as the bus example in the toolexam directory.

class Bus : public RWCollectable  {
  RWDECLARE_COLLECTABLE(Bus)

public:

   Bus();
   Bus(int busno, const RWCString& driver);
   ~Bus();

   // Inherited from class "RWCollectable":
   Rwspace     binaryStoreSize() const;
   int         compareTo(const RWCollectable*) const;
   RWBoolean   isEqual(const RWCollectable*) const;
   unsigned    hash() const;
   void        restoreGuts(RWFile&);
   void        restoreGuts(RWvistream&);
   void        saveGuts(RWFile&) const;
   void        saveGuts(RWvostream&) const;

   void        addPassenger(const char* name);
   void        addCustomer(const char* name);
   size_t      customers() const;
   size_t      passengers() const;
   RWCString   driver() const    {return driver_;}
   int         number() const    {return busNumber_;}

private:

   RWSet       customers_;
   RWSet*      passengers_;
   int         busNumber_;
   RWCString   driver_;
};

class Client : public RWCollectable  {
  RWDECLARE_COLLECTABLE(Client)
  Client(const char* name) : name_(name) {}
private:
  RWCString    name_;
//ignore other client information for this example
};

Note how both classes inherit from RWCollectable. We have chosen to implement the set of customers by using class RWSet, which does not allow duplicate entries. This will guarantee that the same person is not entered into the customer list more than once. For the same reason, we have also chosen to implement the set of passengers using class RWSet. However, we have chosen to have this set live on the heap. This will help illustrate some points in the coming discussion.


Previous file Table of Contents Next file