Comportamento polimorfico

Il polimorfismo ( poly = molti, morphe = forma) è la capacità di trattare molte forme diverse di un oggetto come se fossero la stessa. Il polimorfismo si ottiene in C®++ utilizzando l'ereditarietà e le funzioni virtuali.

Si consideri lo scenario in cui tre moduli ExpenseForm, LoanForm, PurchaseForm ) sono specializzazioni di un modulo generale:
Gerarchia di classi di moduli con la classe padre Form e le classi figlie ExpenseForm, LoanForm, e PurchaseForm

Ogni modulo deve essere stampato prima o poi. Nella programmazione procedurale, avremmo codificato una funzione di stampa per gestire i tre diversi moduli oppure avremmo scritto tre funzioni diverse printExpenseForm, printLoanForm, printPurchaseForm ).

In C++, questo risultato può essere ottenuto in modo molto più elegante come segue:
 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();
};
Ciascuna di queste funzioni sovrascritte viene implementata in modo che ogni modulo venga stampato correttamente. Ora un'applicazione che utilizza oggetti modulo può fare questo:

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

Qui vengono creati dieci oggetti che possono essere una qualsiasi combinazione di moduli di spesa, prestito e acquisto. Tuttavia, poiché si tratta di puntatori alla classe base, Form, non è necessario sapere quale tipo di oggetto Form abbiamo; il metodo di stampa corretto viene richiamato automaticamente.

Nelle classi Foundation è disponibile un comportamento polimorfico limitato. Nella classe base IccResource sono definite tre funzioni virtuali:

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

buffer

);

Questi metodi sono stati implementati nelle sottoclassi di IccResource quando possibile:

Classe cancellare ottenere porre
IccConsole × ×
IccDataQueue
IccJournal × ×
IccSession ×
IccTempStore
IccTerminal

Questi metodi virtuali sono non supportati da tutte le sottoclassi di IccResource, tranne quelle della tabella.

Nota: Le implementazioni predefinite di clear, get e put nella classe base IccResource lanciano un'eccezione per evitare che l'utente chiami un metodo non supportato.

Esempio di comportamento polimorfico

Il seguente esempio si trova nella directory samples come file ICC$RES2. Viene qui presentato senza le richieste di IO del terminale. Vedere i programmi di esempio in C++.

#include "icceh.hpp"
#include "iccmain.hpp"
char* dataItems[] =
{
"Hello World - item 1",
"Hello World - item 2",
"Hello World - item 3"
};
void IccUserControl::run()
{
Qui il codice include le intestazioni della classe Foundation e la funzione principale. dataItems contiene alcuni esempi di dati. Scriviamo il codice della nostra applicazione nel metodo run della classe IccUserControl.
 IccBuf buffer( 50 );
IccResource* pObj[2];
Creiamo un oggetto IccBuf (50 byte inizialmente) per contenere i nostri dati. Viene dichiarato un array di due puntatori a oggetti IccResource.
 pObj[0] = new IccDataQueue("ICCQ");
pObj[1] = new IccTempStore("ICCTEMPS");
Creiamo due oggetti le cui classi sono derivate da IccResource : IccDataQueue e IccTempStore.
 for ( short index=0; index <= 1 ; index++ )
{
pObj[index]->clear();
}
Per entrambi gli oggetti invochiamo il metodo clear. Questo viene gestito in modo diverso da ciascun oggetto, in modo trasparente per il programma applicativo; si tratta di un comportamento polimorfico.
 for ( index=0; index <= 1 ; index++ )
{
for (short j=1 ; j <= 3 ; j++)
{
buffer = dataItems[j-1];
pObj[index]->put( buffer );
}
}
Ora inseriamo tre elementi di dati in ciascuno dei nostri oggetti risorsa. Anche in questo caso, il metodo put risponde alla richiesta in modo appropriato al tipo di oggetto.
 for ( index=0; index <= 1 ; index++ )
{
buffer = pObj[index]->get();
while (pObj[index]->condition() == IccCondition::NORMAL)
{
buffer = pObj[index]->get();
}
delete pObj[index];
}
return;
}

Gli elementi di dati vengono riletti da ciascuno dei nostri oggetti risorsa utilizzando il metodo get. Eliminiamo gli oggetti risorsa e restituiamo il controllo a CICS®.