Symbian
Symbian OS Library

SYMBIAN OS V9.3

[Index] [Spacer] [Previous] [Next]



MClasses1-3: abstract interface classes


Example Code

These are the main files contained in the examples. Some extra files may be needed to run the examples, and these will be found in the appropriate examples directory.

MClasses1

// MClasses1.cpp
//
// Copyright (c) 2000 Symbian Ltd.  All rights reserved.

/*
    Demonstrate use of M classes, or mixins - the
    only use of multiple inheritance that has been
    sanctioned by the E32 architecture team

    This example shows how mixins can be used to
    pass some protocol, and an associated object, from
    a protocol provider to an protocol user.  The user
    is not supposed to know everything about the provider,
    only about the protocol it's interested in.

    In this specific example, the provider is derived 
    from a CProtocol class.
*/

#include "CommonFramework.h"

//////////////////////////////////////////////////////////////////////////////
//
// -----> CProtocol (definition)
//
// A protocol class for mixing in
//
//////////////////////////////////////////////////////////////////////////////
class CProtocol : public CBase
    {
public:
    virtual void HandleEvent(TInt aEventCode)=0;
    };


//////////////////////////////////////////////////////////////////////////////
//
// -----> CProtocolUser (definition)
//
// Define a protocol user which uses this protocol
//
//////////////////////////////////////////////////////////////////////////////
class CProtocolUser : public CBase
    {
public:
      // Construction
    static CProtocolUser* NewLC();
    static CProtocolUser* NewL();

      // Destruction
    ~CProtocolUser();

      // Some function which uses a protocol
    void DoSomething(CProtocol* aProtocol);

protected:
      // Construction assistance
    void ConstructL();
    };


//////////////////////////////////////////////////////////////////////////////
//
// -----> CProtocolProvider (definition)
//
// A simple class which uses the mixin
//
//////////////////////////////////////////////////////////////////////////////
class CProtocolProvider : public CProtocol
    {
public:
      // Construction
    static CProtocolProvider* NewLC();

      // Destruction
    ~CProtocolProvider();

      // Calls the protocol user
    void CallProtocolUser();

      // Implement the protocol (handles the protocol)
    void HandleEvent(TInt aEventCode);

protected:
      // Construction assistance
    void ConstructL();

private:
      // data member defined by this class
    CProtocolUser* iProtocolUser;
    };


//////////////////////////////////////////////////////////////////////////////
//
// -----> CProtocolUser (implementation)
//
//////////////////////////////////////////////////////////////////////////////
CProtocolUser* CProtocolUser::NewLC()
    {
    CProtocolUser* self=new(ELeave) CProtocolUser;
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
    }

CProtocolUser* CProtocolUser::NewL()
    {
    CProtocolUser* self=NewLC();
    CleanupStack::Pop();
    return self;
    }

CProtocolUser::~CProtocolUser()
    {
    }

void CProtocolUser::ConstructL()
    {
    }

void CProtocolUser::DoSomething(CProtocol* aProtocol)
    {
      // Do something that requires a protocol
    _LIT(KTxtExtSystemDoing,"External system doing something\n");
    console->Printf(KTxtExtSystemDoing);
    _LIT(KTxtInvokingProtocol,"invoking protocol - event 3\n");
    console->Printf(KTxtInvokingProtocol);
      // Handle an event
    aProtocol->HandleEvent(3);
    }


//////////////////////////////////////////////////////////////////////////////
//
// -----> CProtocolProvider (implementation)
//
//////////////////////////////////////////////////////////////////////////////
CProtocolProvider* CProtocolProvider::NewLC()
    {
    CProtocolProvider* self=new(ELeave) CProtocolProvider;
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
    };

CProtocolProvider::~CProtocolProvider()
    {
    delete iProtocolUser;
    }

void CProtocolProvider::ConstructL()
    {
    iProtocolUser=CProtocolUser::NewL();
    }

void CProtocolProvider::CallProtocolUser()
    { 
      // Call the protocol user to do some work
    _LIT(KTxtCallProtUser,"CProtocolProvider calling protocol user\n");
    console->Printf(KTxtCallProtUser);
    iProtocolUser->DoSomething(this);

            // pass ourselves, disguised as our (unique)
            // base class, so the protocol can be called
            // back by the protocol user
    }

void CProtocolProvider::HandleEvent(TInt aEventCode)
    { 
      // A concrete implementation of the abstract protocol.
      // Handle an event in the protocol user
    _LIT(KFormat1,"CProtocolProvider handling event %d\n");
    console->Printf(KFormat1,aEventCode);
    }


//////////////////////////////////////////////////////////////////////////////
//
// Do the example
//
//////////////////////////////////////////////////////////////////////////////
LOCAL_C void doExampleL()
    {
      // show use of mixin with simple class
    CProtocolProvider* simpleProvider=CProtocolProvider::NewLC();
      // call protocol user
    simpleProvider->CallProtocolUser();
      // Remove simpleProvider from cleanup stack and destroy
    CleanupStack::PopAndDestroy();
    }

// BLD.INF
// Component description file
//
// Copyright (c) 2000 Symbian Ltd.  All rights reserved.

PRJ_MMPFILES

MClasses1.mmp

// MClasses1.mmp
//
// Copyright (c) 2000 Symbian Ltd.  All rights reserved.

// using relative paths for sourcepath and user includes

TARGET        MClasses1.exe
TARGETTYPE    exe
UID           0
VENDORID 0x70000001

SOURCEPATH    .
SOURCE        MClasses1.cpp

USERINCLUDE   .
USERINCLUDE   ..\CommonFramework
SYSTEMINCLUDE \Epoc32\include

LIBRARY       euser.lib

MClasses2

// MClasses2.cpp
//
// Copyright (c) 2000 Symbian Ltd.  All rights reserved.

/*
    Demonstrate use of M classes, or mixins - the
    only use of multiple inheritance that has been
    sanctioned by the E32 architecture team

    This example shows how mixins can be used to
    pass some protocol, and an associated object, from
    a protocol provider to an protocol user.  The user
    is not supposed to know everything about the provider,
    only about the protocol it's interested in.

    In this specific example, the provider contains a pointer 
    to the _real provider_: the provider is derived
    from the protocol base class, but the real provider is not.
    The real provider may thus honour many protocols.
*/

#include "CommonFramework.h"

//////////////////////////////////////////////////////////////////////////////
//
// -----> CProtocol (definition)
//
// A protocol class for mixing in
//
//////////////////////////////////////////////////////////////////////////////
class TProtocol
    {
public:
    virtual void HandleEvent(TInt aEventCode)=0;
    };


//////////////////////////////////////////////////////////////////////////////
//
// -----> CProtocolUser (definition)
//
// Define a protocol user which uses this protocol
//
//////////////////////////////////////////////////////////////////////////////
class CProtocolUser : public CBase
    {
public:
      // Construction
    static CProtocolUser* NewLC();
    static CProtocolUser* NewL();

      // Destruction
    ~CProtocolUser();

      // Some function which uses a protocol
    void DoSomething(TProtocol* aProtocol);

protected:
      // Construction assistance
    void ConstructL();
    };


//////////////////////////////////////////////////////////////////////////////
//
// -----> CProtocolProvider (definition)
//
// A simple class which uses the mixin
//
//////////////////////////////////////////////////////////////////////////////
class TProtocolProvider;
class CProtocolProvider : public CBase
    {
public:
      // Construction
    static CProtocolProvider* NewLC();

      // Destruction
    ~CProtocolProvider();

      // Calls the protocol user
    void CallProtocolUser();

      // Implement the protocol (handles the protocol)
    void HandleEvent(TInt aEventCode);

protected:
      // Construction assistance
    void ConstructL();

private:
      // data members defined by this class
    CProtocolUser*     iProtocolUser;
    TProtocolProvider* iProviderProtocol;
    };


//////////////////////////////////////////////////////////////////////////////
//
// -----> TProtocolProvider (definition)
//
// Define protocol implementation which passes on the implementation
// to a real protocol provider
//
//////////////////////////////////////////////////////////////////////////////
class TProtocolProvider : public TProtocol
    {
public:
      // Construction
    TProtocolProvider(CProtocolProvider* aProvider);

      // The protocol itself
    void HandleEvent(TInt aEventCode);

private:
      // The real provider
    CProtocolProvider* iProvider;
    };


//////////////////////////////////////////////////////////////////////////////
//
// -----> CProtocolUser (implementation)
//
//////////////////////////////////////////////////////////////////////////////
CProtocolUser* CProtocolUser::NewLC()
    {
    CProtocolUser* self=new(ELeave) CProtocolUser;
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
    }

CProtocolUser* CProtocolUser::NewL()
    {
    CProtocolUser* self=NewLC();
    CleanupStack::Pop();
    return self;
    }

CProtocolUser::~CProtocolUser()
    {
    }

void CProtocolUser::ConstructL()
    {
    }

void CProtocolUser::DoSomething(TProtocol* aProtocol)
    {
      // Do something that requires a protocol
    _LIT(KTxtExtSystemDoing,"External system doing something\n");
    console->Printf(KTxtExtSystemDoing);
    _LIT(KTxtInvokingProtocol,"invoking protocol - event 3\n");
    console->Printf(KTxtInvokingProtocol);
      // Handle an event
    aProtocol->HandleEvent(3);
    }


//////////////////////////////////////////////////////////////////////////////
//
// -----> TProtocolProvider (implementation)
//
//////////////////////////////////////////////////////////////////////////////
TProtocolProvider::TProtocolProvider(CProtocolProvider* aProvider)
        : iProvider(aProvider)
    {
    }

// see later for definition of HandleEvent()


//////////////////////////////////////////////////////////////////////////////
//
// -----> CProtocolProvider (implementation)
//
//////////////////////////////////////////////////////////////////////////////
CProtocolProvider* CProtocolProvider::NewLC()
    {
    CProtocolProvider* self=new(ELeave) CProtocolProvider;
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
    };

CProtocolProvider::~CProtocolProvider()
    {
    delete iProtocolUser;
    delete iProviderProtocol;
    }

void CProtocolProvider::ConstructL()
    {
    iProtocolUser=CProtocolUser::NewL();
    iProviderProtocol=new(ELeave) TProtocolProvider(this);
    }

void CProtocolProvider::CallProtocolUser()
    { 
      // Call the protocol user to do some work
    _LIT(KTxtCallProtUser,"CProtocolProvider calling protocol user\n");
    console->Printf(KTxtCallProtUser);
    iProtocolUser->DoSomething(iProviderProtocol);
            // pass the intermediary, which implements the
            // protocol by passing it on to us,
            // to the protocol user
    }

void CProtocolProvider::HandleEvent(TInt aEventCode)
    { 
      // A concrete implementation of the abstract protocol.
      // Handle an event in the protocol user
    _LIT(KFormat1,"CProtocolProvider handling event %d\n");
    console->Printf(KFormat1,aEventCode);
    }

void TProtocolProvider::HandleEvent(TInt aEventCode)
    {
      // A concrete definition of TProtocol::HandleEvent()
    _LIT(KTxtHandling,"Handling through intermediary\n");
    console->Printf(KTxtHandling);
    iProvider->HandleEvent(aEventCode);
    }


//////////////////////////////////////////////////////////////////////////////
//
// Do the example
//
//////////////////////////////////////////////////////////////////////////////
LOCAL_C void doExampleL()
    {
      // show use of mixin with simple class
    CProtocolProvider* simpleProvider=CProtocolProvider::NewLC();
      // call protocol user
    simpleProvider->CallProtocolUser();
      // Remove simpleProvider from cleanup stack and destroy
    CleanupStack::PopAndDestroy();
    }

// BLD.INF
// Component description file
//
// Copyright (c) 2000 Symbian Ltd.  All rights reserved.

PRJ_MMPFILES

MClasses2.mmp

// MClasses2.mmp
//
// Copyright (c) 2000 Symbian Ltd.  All rights reserved.

// using relative paths for sourcepath and user includes

TARGET        MClasses2.exe
TARGETTYPE    exe
UID           0
VENDORID 0x70000001

SOURCEPATH    .
SOURCE        MClasses2.cpp

USERINCLUDE   .
USERINCLUDE   ..\CommonFramework
SYSTEMINCLUDE \Epoc32\include

LIBRARY       euser.lib

MClasses3

// MClasses3.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//



/*
    Demonstrate use of M classes, or mixins - the
    only use of multiple inheritance that has been
    sanctioned by the E32 architecture team

    This example shows how mixins can be used to
    pass some protocol, and an associated object, from
    a protocol provider to an protocol user.  The user
    is not supposed to know everything about the provider,
    only about the protocol it's interested in.

    In this specific example, the provider is derived from
    an appropriate base class, and a mixin class representing
    the protocol. The benefits of the method shown in example EUTYPEM2
    are thus gained, without the inconvenience of intermediary
    classes.

*/

#include "CommonFramework.h"

//////////////////////////////////////////////////////////////////////////////
//
// -----> CProtocol (definition)
//
// A protocol class for mixing in
//
//////////////////////////////////////////////////////////////////////////////
class MProtocol
    {
public:
    virtual void HandleEvent(TInt aEventCode)=0;
    };


//////////////////////////////////////////////////////////////////////////////
//
// -----> CProtocolUser (definition)
//
// Define a protocol user which uses this protocol
//
//////////////////////////////////////////////////////////////////////////////
class CProtocolUser : public CBase
    {
public:
      // Construction
    static CProtocolUser* NewLC();
    static CProtocolUser* NewL();

      // Destruction
    ~CProtocolUser();

      // Some function which uses a protocol
    void DoSomething(MProtocol* aProtocol);

protected:
      // Construction assistance
    void ConstructL();
    };


//////////////////////////////////////////////////////////////////////////////
//
// -----> CProtocolProvider (definition)
//
// A simple class which uses the mixin
//
//////////////////////////////////////////////////////////////////////////////
class CProtocolProvider : public CBase, public MProtocol
    {
public:
      // Construction
    static CProtocolProvider* NewLC();

      // Destruction
    ~CProtocolProvider();

      // Calls the protocol user
    void CallProtocolUser();

      // Implement the protocol (handles the protocol)
    void HandleEvent(TInt aEventCode);

protected:
      // Construction assistance
    void ConstructL();

private:
      // data members defined by this class
    CProtocolUser*     iProtocolUser;
    };


//////////////////////////////////////////////////////////////////////////////
//
// -----> CProtocolUser (implementation)
//
//////////////////////////////////////////////////////////////////////////////
CProtocolUser* CProtocolUser::NewLC()
    {
    CProtocolUser* self=new(ELeave) CProtocolUser;
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
    }

CProtocolUser* CProtocolUser::NewL()
    {
    CProtocolUser* self=NewLC();
    CleanupStack::Pop();
    return self;
    }

CProtocolUser::~CProtocolUser()
    {
    }

void CProtocolUser::ConstructL()
    {
    }

void CProtocolUser::DoSomething(MProtocol* aProtocol)
    {
      // Do something that requires a protocol
    _LIT(KTxtExtSystemDoing,"External system doing something\n");
    console->Printf(KTxtExtSystemDoing);
    _LIT(KTxtInvokingProtocol,"invoking protocol - event 3\n");
    console->Printf(KTxtInvokingProtocol);
      // Handle an event
    aProtocol->HandleEvent(3);
    }


//////////////////////////////////////////////////////////////////////////////
//
// -----> CProtocolProvider (implementation)
//
//////////////////////////////////////////////////////////////////////////////
CProtocolProvider* CProtocolProvider::NewLC()
    {
    CProtocolProvider* self=new(ELeave) CProtocolProvider;
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
    };

CProtocolProvider::~CProtocolProvider()
    {
    delete iProtocolUser;
    }

void CProtocolProvider::ConstructL()
    {
    iProtocolUser=CProtocolUser::NewL();
    }

void CProtocolProvider::CallProtocolUser()
    { 
      // Call the protocol user to do some work
    _LIT(KTxtCallProtUser,"CProtocolProvider calling protocol user\n");
    console->Printf(KTxtCallProtUser);
    iProtocolUser->DoSomething(this);
     // pass ourselves, disguised as our mixin
     // protocol base, to the protocol user
    }

void CProtocolProvider::HandleEvent(TInt aEventCode)
    { 
      // A concrete implementation of the abstract protocol.
      // Handle an event in the protocol user
    _LIT(KFormat1,"CProtocolProvider handling event %d\n");
    console->Printf(KFormat1,aEventCode);
    }


//////////////////////////////////////////////////////////////////////////////
//
// Do the example
//
//////////////////////////////////////////////////////////////////////////////
LOCAL_C void doExampleL()
    {
      // show use of mixin with simple class
    CProtocolProvider* simpleProvider=CProtocolProvider::NewLC();
      // call protocol user
    simpleProvider->CallProtocolUser();
      // Remove simpleProvider from cleanup stack and destroy
    CleanupStack::PopAndDestroy();
    }

// BLD.INF
//
// Copyright (c) 2000 Symbian Ltd.  All rights reserved.
//


PRJ_MMPFILES

MClasses3.mmp

// MClasses3.MMP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

// using relative paths for sourcepath and user includes

TARGET        MClasses3.exe
TARGETTYPE    exe
UID 0
VENDORID 0x70000001

SOURCEPATH    .
SOURCE        MClasses3.cpp
USERINCLUDE   .
USERINCLUDE   ..\CommonFramework
SYSTEMINCLUDE \epoc32\include
LIBRARY       euser.lib

[Top]


Description

The three examples show the use of M (abstract interface) classes, the only type of multiple inheritance used in Symbian OS.

They show how interfaces can be used to define a protocol. The interface is implemented by a protocol provider, and called by a protocol user. The user is not supposed to know anything about the provider's implementation, only about the protocol it's interested in.

[Top]


Build

The source code for this example application can be found in the directories:

examples\Basics\MClasses1

examples\Basics\MClasses2

examples\Basics\MClasses3

They may be in the directory in which you installed Symbian OS, or they may be in src\common\developerlibrary\. They each include the two project files needed for building: bld.inf and the .mmp file.

The Symbian OS build process describes how to build these applications. They results in executables called:

\epoc32\release\<target>\<urel or udeb>\MCLASSES1.EXE.

\epoc32\release\<target>\<urel or udeb>\MCLASSES2.EXE.

\epoc32\release\<target>\<urel or udeb>\MCLASSES3.EXE.

[Top]


Usage

Run the executables MCLASSES1.EXE, MCLASSES2.EXE and MCLASSES3.EXE.

Executables for the emulator targets wins and winscw can be run on your PC. Executables for ARM targets must be copied to your target platform before being run.