Polymorphic Behavior

Polymorphism (poly = many, morphe = form) is the ability to treat many different forms of an object as if they were the same.

Polymorphism is achieved in C++ by using inheritance and virtual functions. Consider the scenario where we have three forms (ExpenseForm, LoanForm, PurchaseForm) that are specializations of a general Form:

                          Form
                            |
            *---------------*---------------*
            |               |               |
     ExpenseForm        LoanForm      PurchaseForm

Each form needs printing at some time. In procedural programming, we would either code a print function to handle the three different forms or we would write three different functions (printExpenseForm, printLoanForm, printPurchaseForm).

In C++ this can be achieved far more elegantly as follows:

   class   Form   {
   public:
      virtual void print();
   };
   class ExpenseForm : public Form {
   public:
      virtual void print();
   };
   class LoanForm : public Form {
   public:
      virtual void print();
   };
   class PurchaseForm : public Form {
   public:
      virtual void print();
   };

Each of these overridden functions is implemented so that each form prints correctly. Now an application using form objects can do this:

   Form* pForm[10]
   //create Expense/Loan/Purchase Forms...
   for (short i=0 ; i < 9 ; i++)
      pForm->print();

Here we create ten objects that might be any combination of Expense, Loan, and Purchase Forms. However, because we are dealing with pointers to the base class, Form, we do not need to know which sort of form object we have; the correct print method is called automatically.

Limited polymorphic behavior is available in the Foundation Classes. Three virtual functions are defined in the base class IccResource:

   virtual void clear();
   virtual const IccBuf& get();
   virtual void put(const IccBuf& buffer);

These methods have been implemented in the subclasses of IccResource wherever possible:

Class clear get put
IccConsole × × X
IccDataQueue X X X
IccJournal × × X
IccSession × X X
IccTempStore X X X
IccTerminal X X X

These virtual methods are not supported by any subclasses of IccResource except those in the table above.

Note:
The default implementations of clear, get, and put in the base class IccResource throw an exception to prevent the user from calling an unsupported method.

Example of polymorphic behavior

The following sample can be found in the samples directory (see Sample source code) as file ICC$RES2. It is presented here without the terminal IO requests.

#include "icceh.hpp"
#include "iccmain.hpp"
char* dataItems[] =
{
  "Hello World - item 1",
  "Hello World - item 2",
  "Hello World - item 3"
};
void IccUserControl::run()
{

Here we include Foundation Class headers and the main function. dataItems contains some sample data items. We write our application code in the run method of IccUserControl class.

  IccBuf buffer( 50 );
  IccResource* pObj[2];

We create an IccBuf object (50 bytes initially) to hold our data items. An array of two pointers to IccResource objects is declared.

  pObj[0] = new IccDataQueue("ICCQ");
  pObj[1] = new IccTempStore("ICCTEMPS");

We create two objects whose classes are derived from IccResource - IccDataQueue and IccTempStore.

  for ( short index=0; index <= 1 ; index++ )
  {
    pObj[index]->clear();
  }

For both objects we invoke the clear method. This is handled differently by each object in a way that is transparent to the application program; this is polymorphic behavior.

  for ( index=0; index <= 1 ; index++ )
  {
    for (short j=1 ; j <= 3 ; j++)
    {
      buffer = dataItems[j-1];
      pObj[index]->put( buffer );
    }
  }

Now we put three data items in each of our resource objects. Again the put method responds to the request in a way that is appropriate to the object type.

  for ( index=0; index <= 1 ; index++ )
  {
    buffer = pObj[index]->get();
    while (pObj[index]->condition() == IccCondition::NORMAL)
    {
      buffer = pObj[index]->get();
    }
    delete pObj[index];
  }
  return;
}

The data items are read back in from each of our resource objects using the get method. We delete the resource objects and return control to CICS®.

[[ Contents Previous Page | Next Page Index ]]