Compartilhar via


O que é uma interface COM?

Se você conhece C# ou Java, as interfaces devem ser um conceito familiar. Uma interface define um conjunto de métodos que um objeto pode dar suporte, sem ditar nada sobre a implementação. A interface marca um limite claro entre o código que chama um método e o código que implementa o método . Em termos de ciência da computação, o chamador é dissociado da implementação.

ilustração mostrando o limite da interface entre um objeto e um aplicativo

No C++, o equivalente mais próximo de uma interface é uma classe virtual pura, ou seja, uma classe que contém apenas métodos virtuais puros e nenhum outro membro. Aqui está um exemplo hipotético de uma interface:

// The following is not actual COM.

// Pseudo-C++:

interface IDrawable
{
    void Draw();
};

A ideia deste exemplo é que um conjunto de objetos em algumas bibliotecas gráficas seja desenhado. A IDrawable interface define as operações que qualquer objeto desenhável deve dar suporte. (Por convenção, os nomes de interface começam com "I".) Neste exemplo, a IDrawable interface define uma única operação: Draw.

Todas as interfaces são abstratas, portanto, um programa não pôde criar uma instância de um IDrawable objeto como tal. Por exemplo, o código a seguir não seria compilado.

IDrawable draw;
draw.Draw();

Em vez disso, a biblioteca de gráficos fornece objetos que implementam a IDrawable interface . Por exemplo, a biblioteca pode fornecer um objeto de forma para formas de desenho e um objeto bitmap para desenhar imagens. No C++, isso é feito herdando de uma classe base abstrata comum:

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.
};

As Shape classes e Bitmap definem dois tipos distintos de objeto desenhável. Cada classe herda de IDrawable e fornece sua própria implementação do Draw método . Naturalmente, as duas implementações podem ser consideravelmente diferentes. Por exemplo, o Shape::Draw método pode rasterizar um conjunto de linhas, enquanto Bitmap::Draw blit uma matriz de pixels.

Um programa que usa essa biblioteca gráfica manipularia Shape objetos e Bitmap por meio IDrawable de ponteiros, em vez de usar Shape ponteiros ou Bitmap diretamente.

IDrawable *pDrawable = CreateTriangleShape();

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

Aqui está um exemplo que faz loop sobre uma matriz de IDrawable ponteiros. A matriz pode conter uma variedade heterogênea de formas, bitmaps e outros objetos gráficos, desde que cada objeto na matriz herda IDrawable.

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

Um ponto importante sobre COM é que o código de chamada nunca vê o tipo da classe derivada. Em outras palavras, você nunca declararia uma variável do tipo Shape ou Bitmap em seu código. Todas as operações em formas e bitmaps são executadas usando IDrawable ponteiros. Dessa forma, o COM mantém uma separação estrita entre interface e implementação. Os detalhes de implementação das Shape classes e Bitmap podem ser alterados, por exemplo, para corrigir bugs ou adicionar novos recursos, sem alterações no código de chamada.

Em uma implementação C++, as interfaces são declaradas usando uma classe ou estrutura.

Observação

Os exemplos de código neste tópico destinam-se a transmitir conceitos gerais, não prática do mundo real. A definição de novas interfaces COM está além do escopo desta série, mas você não definiria uma interface diretamente em um arquivo de cabeçalho. Em vez disso, uma interface COM é definida usando uma linguagem chamada IDL (Interface Definition Language). O arquivo IDL é processado por um compilador de IDL, que gera um arquivo de cabeçalho C++.

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

Quando você trabalha com COM, é importante lembrar que as interfaces não são objetos. São coleções de métodos que os objetos devem implementar. Vários objetos podem implementar a mesma interface, conforme mostrado com os Shape exemplos e Bitmap . Além disso, um objeto pode implementar várias interfaces. Por exemplo, a biblioteca de gráficos pode definir uma interface chamada ISerializable que dá suporte a salvar e carregar objetos gráficos. Agora considere as seguintes declarações de classe:

// 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
{
    ...
};

Neste exemplo, a Bitmap classe implementa ISerializable. O programa pode usar esse método para salvar ou carregar o bitmap. No entanto, a Shape classe não implementa ISerializable, portanto, ela não expõe essa funcionalidade. O diagrama a seguir mostra as relações de herança neste exemplo.

ilustração mostrando a herança da interface, com as classes shape e bitmap apontando para idrawable, mas apenas bitmap apontando para iserializável

Esta seção examinou a base conceitual das interfaces, mas até agora não vimos o código COM real. Começaremos com a primeira coisa que qualquer aplicativo COM deve fazer: Inicializar a biblioteca COM.

Avançar

Inicializando a biblioteca COM