Condividi tramite


Che cos'è un'interfaccia COM?

Se si conosce C# o Java, le interfacce devono essere un concetto familiare. Un'interfaccia definisce un set di metodi che un oggetto può supportare, senza dettatura dell'implementazione. L'interfaccia contrassegna un limite chiaro tra il codice che chiama un metodo e il codice che implementa il metodo . In termini di informatica, il chiamante è disaccoppiato dall'implementazione.

illustrazione che mostra il limite di interfaccia tra un oggetto e un'applicazione

In C++, l'equivalente più vicino a un'interfaccia è una classe virtuale pura, ovvero una classe che contiene solo metodi virtuali puri e nessun altro membro. Ecco un esempio ipotetico di un'interfaccia:

// The following is not actual COM.

// Pseudo-C++:

interface IDrawable
{
    void Draw();
};

L'idea di questo esempio è che un set di oggetti in alcune librerie grafiche è disegnabile. L'interfaccia IDrawable definisce le operazioni che devono essere supportate da qualsiasi oggetto drawable. Per convenzione, i nomi di interfaccia iniziano con "I".) In questo esempio l'interfaccia IDrawable definisce una singola operazione: Draw.

Tutte le interfacce sono astratte, quindi un programma non può creare un'istanza di un IDrawable oggetto come tale. Ad esempio, il codice seguente non viene compilato.

IDrawable draw;
draw.Draw();

La libreria grafica fornisce invece oggetti che implementano l'interfaccia IDrawable . Ad esempio, la libreria potrebbe fornire un oggetto shape per disegnare forme e un oggetto bitmap per il disegno di immagini. In C++, questa operazione viene eseguita ereditando da una classe base astratta comune:

class Shape : public IDrawable
{
public:
    virtual void Draw();    // Override Draw and provide implementation.
};

class Bitmap : public IDrawable
{
public:
    virtual void Draw();    // Override Draw and provide implementation.
};

Le Shape classi e Bitmap definiscono due tipi distinti di oggetto drawable. Ogni classe eredita da IDrawable e fornisce la propria implementazione del Draw metodo . Naturalmente, le due implementazioni potrebbero differire notevolmente. Ad esempio, il Shape::Draw metodo potrebbe rasterizzare un set di righe, mentre Bitmap::Draw avrebbe generato un'ampiezza di una matrice di pixel.

Un programma che usa questa libreria grafica modifica Shape e oggetti tramite IDrawable puntatori, anziché usare Shape direttamente i puntatori o BitmapBitmap .

IDrawable *pDrawable = CreateTriangleShape();

if (pDrawable)
{
    pDrawable->Draw();
}

Di seguito è riportato un esempio che esegue un ciclo su una matrice di IDrawable puntatori. La matrice può contenere un assortimento eterogeneo di forme, bitmap e altri oggetti grafici, purché ogni oggetto nella matrice erediti IDrawable.

void DrawSomeShapes(IDrawable **drawableArray, size_t count)
{
    for (size_t i = 0; i < count; i++)
    {
        drawableArray[i]->Draw();
    }
}

Un punto chiave su COM è che il codice chiamante non vede mai il tipo della classe derivata. In altre parole, non si dichiara mai una variabile di tipo Shape o Bitmap nel codice. Tutte le operazioni su forme e bitmap vengono eseguite usando IDrawable puntatori. In questo modo, COM mantiene una stretta separazione tra l'interfaccia e l'implementazione. I dettagli di implementazione delle Shape classi e Bitmap possono cambiare, ad esempio per correggere i bug o aggiungere nuove funzionalità, senza modifiche al codice chiamante.

In un'implementazione C++ le interfacce vengono dichiarate usando una classe o una struttura.

Nota

Gli esempi di codice in questo argomento sono destinati a trasmettere concetti generali, non pratiche reali. La definizione di nuove interfacce COM non rientra nell'ambito di questa serie, ma non si definirà un'interfaccia direttamente in un file di intestazione. Al contrario, un'interfaccia COM viene definita usando un linguaggio denominato IDL (Interface Definition Language). Il file IDL viene elaborato da un compilatore IDL, che genera un file di intestazione C++.

class IDrawable
{
public:
    virtual void Draw() = 0;
};

Quando si lavora con COM, è importante ricordare che le interfacce non sono oggetti. Sono raccolte di metodi che gli oggetti devono implementare. Diversi oggetti possono implementare la stessa interfaccia, come illustrato con gli Shape esempi e Bitmap . Inoltre, un oggetto può implementare diverse interfacce. Ad esempio, la libreria grafica potrebbe definire un'interfaccia denominata ISerializable che supporta il salvataggio e il caricamento di oggetti grafici. Si considerino ora le dichiarazioni di classe seguenti:

// An interface for serialization.
class ISerializable
{
public:
    virtual void Load(PCWSTR filename) = 0;    // Load from file.
    virtual void Save(PCWSTR filename) = 0;    // Save to file.
};

// Declarations of drawable object types.

class Shape : public IDrawable
{
    ...
};

class Bitmap : public IDrawable, public ISerializable
{
    ...
};

In questo esempio la Bitmap classe implementa ISerializable. Il programma può usare questo metodo per salvare o caricare la bitmap. Tuttavia, la Shape classe non implementa ISerializable, quindi non espone tale funzionalità. Il diagramma seguente illustra le relazioni di ereditarietà in questo esempio.

illustrazione che mostra l'ereditarietà dell'interfaccia, con le classi shape e bitmap che puntano a idrawable, ma solo bitmap che puntano a iserializable

Questa sezione ha esaminato la base concettuale delle interfacce, ma finora non è stato rilevato codice COM effettivo. Si inizierà con la prima operazione che deve essere eseguita da qualsiasi applicazione COM: Inizializzare la libreria COM.

Prossima

Inizializzazione della libreria COM