Delen via


Interfaces (C++/CX)

Hoewel een verw-klasse maximaal één concrete basisklasse kan overnemen, kan deze een willekeurig aantal interfaceklassen implementeren. Een interfaceklasse (of interface-struct) zelf kan meerdere interfaceklassen overnemen (of vereisen), kan de lidfuncties overbelasten en kan typeparameters hebben.

Kenmerken

Een interface heeft deze kenmerken:

  • Een interfaceklasse (of struct) moet worden gedeclareerd binnen een naamruimte en kan openbare of persoonlijke toegankelijkheid hebben. Alleen openbare interfaces worden verzonden naar metagegevens.

  • De leden van een interface kunnen eigenschappen, methoden en gebeurtenissen bevatten.

  • Alle interfaceleden zijn impliciet openbaar en virtueel.

  • Velden en statische leden zijn niet toegestaan.

  • Typen die worden gebruikt als eigenschappen, methodeparameters of retourwaarden kunnen alleen Windows Runtime-typen zijn; dit omvat de fundamentele typen en opsommingsklassetypen.

Declaratie en gebruik

In het volgende voorbeeld ziet u hoe u een interface declareert. U ziet dat een interface kan worden gedeclareerd als een klasse- of structtype.

namespace InterfacesTest
{
    public enum class PlayState {Playing, Paused, Stopped, Forward, Reverse};

    public ref struct MediaPlayerEventArgs sealed
    {
        property PlayState oldState;
        property PlayState newState;
    };

    public delegate void OnStateChanged(Platform::Object^ sender, MediaPlayerEventArgs^ a);
    public interface class IMediaPlayer // or public interface struct IMediaPlayer 
    {
        event OnStateChanged^ StateChanged;
        property Platform::String^ CurrentTitle;
        property PlayState CurrentState;
        void Play();
        void Pause();
        void Stop();
        void Back(float speed);
        void Forward(float speed);
    };
}

Als u een interface wilt implementeren, declareert en implementeert een verw-klasse of verw-struct virtuele methoden en eigenschappen. De interface en de implementatieverwijzingsklasse moeten dezelfde parameternamen gebruiken, zoals wordt weergegeven in dit voorbeeld:

public ref class MyMediaPlayer sealed : public IMediaPlayer
{
public:
    //IMediaPlayer
    virtual event OnStateChanged^ StateChanged;
    virtual property Platform::String^ CurrentTitle;
    virtual property PlayState CurrentState;
    virtual void Play()
    {
        // ...
        auto args = ref new MediaPlayerEventArgs(); 
        args->newState = PlayState::Playing;
        args->oldState = PlayState::Stopped;
        StateChanged(this, args);
    }
    virtual void Pause(){/*...*/}
    virtual void Stop(){/*...*/}
    virtual void Forward(float speed){/*...*/}
    virtual void Back(float speed){/*...*/}
private:
    //...
};

Overnamehiërarchieën van interface

Een interface kan overnemen van een of meer interfaces. Maar in tegenstelling tot een verw-klasse of struct declareert een interface de overgenomen interfaceleden niet. Als interface B wordt overgenomen van interface A en ref-klasse C wordt overgenomen van B, moet C zowel A als B implementeren. Dit wordt weergegeven in het volgende voorbeeld.

public interface struct A { void DoSomething(); };
public interface struct B : A { void DoSomethingMore();};

public ref struct C sealed : B
{
    virtual void DoSomething(){}
    virtual void DoSomethingMore(){}
};


Interface-eigenschappen en -gebeurtenissen implementeren

Zoals u in het vorige voorbeeld kunt zien, kunt u triviale virtuele eigenschappen gebruiken om interface-eigenschappen te implementeren. U kunt ook aangepaste getters en setters opgeven in de implementatieklasse. Zowel de getter als de setter moeten openbaar zijn in een interface-eigenschap.

//Alternate implementation in MediaPlayer class of IMediaPlayer::CurrentTitle
virtual property Platform::String^ CurrentTitle
{
    Platform::String^ get() {return "Now playing: " + _title;}
    void set(Platform::String^ t) {_title = t; }
}

Als een interface een eigenschap alleen ophalen of alleen-instellen declareert, moet de implementatieklasse expliciet een getter of setter opgeven.

public interface class IMediaPlayer
{
    //...
    property Platform::String^ CurrentTitle
    {
        Platform::String^ get();           
    }
};

public ref class MyMediaPlayer3 sealed : public IMediaPlayer
{
public:
    //...
    virtual property Platform::String^ CurrentTitle
    {
        Platform::String^ get() {return "Now playing: " + _title;}
    }
private:
    Platform::String^ _title;
};

U kunt ook aangepaste methoden voor toevoegen en verwijderen implementeren voor gebeurtenissen in de implementatieklasse.

Expliciete interface-implementatie

Wanneer een verw-klasse meerdere interfaces implementeert en deze interfaces methoden hebben waarvan de namen en handtekeningen identiek zijn aan de compiler, kunt u de volgende syntaxis gebruiken om expliciet aan te geven welke interfacemethode een klassemethode implementeert.

public interface class IArtist
{     
    Platform::String^ Draw();
};

public interface class ICowboy
{
    Platform::String^ Draw();
};

public ref class MyClass sealed : public IArtist, ICowboy
{
public:     
    MyClass(){}     
    virtual  Platform::String^ ArtistDraw() = IArtist::Draw {return L"Artist";}
    virtual  Platform::String^ CowboyDraw() = ICowboy::Draw {return L"Cowboy";}
};

Algemene interfaces

In C++/CX wordt het generic trefwoord gebruikt om een geparameteriseerd type Windows Runtime weer te geven. Een geparameteriseerd type wordt verzonden in metagegevens en kan worden gebruikt door code die is geschreven in elke taal die typeparameters ondersteunt. De Windows Runtime definieert enkele algemene interfaces, bijvoorbeeld Windows::Foundation::Collections::IVector<T>, maar biedt geen ondersteuning voor het maken van openbare door de gebruiker gedefinieerde algemene interfaces in C++/CX. U kunt echter persoonlijke algemene interfaces maken.

U kunt als volgt Windows Runtime-typen gebruiken om een algemene interface te maken:

  • Een algemene gebruiker die in een onderdeel is gedefinieerd interface class , mag niet worden verzonden naar het Windows-metagegevensbestand. Daarom kan het geen openbare toegankelijkheid hebben en kan clientcode in andere WINMD-bestanden het niet implementeren. Het kan worden geïmplementeerd door niet-openbare ref-klassen in hetzelfde onderdeel. Een openbare ref-klasse kan een algemeen interfacetype hebben als privélid.

    In het volgende codefragment ziet u hoe u een algemeen fragment interface class declareert en deze vervolgens implementeert in een privéverwklasse en de verw-klasse gebruikt als een privélid in een openbare verw-klasse.

    public ref class MediaFile sealed {};
    
    generic <typename T>
    private interface class  IFileCollection
    {
        property Windows::Foundation::Collections::IVector<T>^ Files;
        Platform::String^  GetFileInfoAsString(T file);
    };
    
    private ref class MediaFileCollection : IFileCollection<MediaFile^>
    {
    public:
        virtual property Windows::Foundation::Collections::IVector<MediaFile^>^ Files;
        virtual Platform::String^  GetFileInfoAsString(MediaFile^ file){return "";}
    };
    
    public interface class ILibraryClient
    {
        bool FindTitle(Platform::String^ title);       
        //...
    };
    
    public ref class MediaPlayer sealed : public IMediaPlayer, public ILibraryClient
    {
    public:
        //IMediaPlayer
        virtual event OnStateChanged^ StateChanged;
        virtual property Platform::String^ CurrentTitle;
        virtual property PlayState CurrentState;
        virtual void Play()
        {
            auto args = ref new MediaPlayerEventArgs(); 
            args->newState = PlayState::Playing;
            args->oldState = PlayState::Stopped;
            StateChanged(this, args);
        }
        virtual void Pause(){/*...*/}
        virtual void Stop(){/*...*/}
        virtual void Forward(float speed){/*...*/}
        virtual void Back(float speed){/*...*/}
    
        //ILibraryClient
        virtual bool FindTitle(Platform::String^ title){/*...*/ return true;}
    
    private:
        MediaFileCollection^ fileCollection;
    
    };
    
  • Een algemene interface moet voldoen aan de standaardinterfaceregels voor toegankelijkheid, leden, vereist relaties, basisklassen enzovoort.

  • Een algemene interface kan een of meer algemene typeparameters aannemen die worden voorafgegaan door typename of class. Niet-type parameters worden niet ondersteund.

  • Een typeparameter kan elk Windows Runtime-type zijn. Dat wil gezegd: de typeparameter kan een verwijzingstype, een waardetype, een interfaceklasse, een gemachtigde, een fundamenteel type of een openbare enumklasse zijn.

  • Een gesloten algemene interface is een interface die overkomt van een algemene interface en concrete typeargumenten voor alle typeparameters specificeert. Het kan overal worden gebruikt waar een niet-algemene privéinterface kan worden gebruikt.

  • Een open algemene interface is een interface met een of meer typeparameters waarvoor nog geen concreet type is opgegeven. Het kan overal worden gebruikt waar een type kan worden gebruikt, inclusief als een typeargument van een andere algemene interface.

  • U kunt alleen een volledige interface parameteriseren, niet afzonderlijke methoden.

  • Typeparameters kunnen niet worden beperkt.

  • Een gesloten algemene interface heeft een impliciet gegenereerde UUID. Een gebruiker kan de UUID niet opgeven.

  • In de interface wordt ervan uitgegaan dat elke verwijzing naar de huidige interface( in een methodeparameter, retourwaarde of eigenschap) naar de huidige instantie verwijst. IMyIntf betekent bijvoorbeeld IMyIntf<T>.

  • Wanneer het type van een methodeparameter een typeparameter is, gebruikt de declaratie van die parameter of variabele de naam van de typeparameter zonder aanwijzer, systeemeigen verwijzing of declaraties te verwerken. Met andere woorden, u schrijft nooit 'T^'.

  • Sjabloonverwklassen moeten privé zijn. Ze kunnen algemene interfaces implementeren en sjabloonparameter T doorgeven aan algemeen argument T. Elke instantie van een sjabloonverwklasse is zelf een verw-klasse.

Zie ook

Typesysteem
Naslaginformatie over C++/CX-taal
Naslaginformatie over naamruimten