Bagikan melalui


Antarmuka (C++/CX)

Meskipun kelas ref dapat mewarisi dari paling banyak satu kelas dasar beton, kelas ini dapat mengimplementasikan sejumlah kelas antarmuka. Kelas antarmuka (atau struktur antarmuka) itu sendiri dapat mewarisi (atau memerlukan) beberapa kelas antarmuka, dapat membebani fungsi anggotanya, dan dapat memiliki parameter jenis.

Karakteristik

Antarmuka memiliki karakteristik ini:

  • Kelas antarmuka (atau struktur) harus dideklarasikan dalam namespace layanan dan mungkin memiliki aksesibilitas publik atau privat. Hanya antarmuka publik yang dipancarkan ke metadata.

  • Anggota antarmuka dapat mencakup properti, metode, dan peristiwa.

  • Semua anggota antarmuka secara implisit bersifat publik dan virtual.

  • Bidang dan anggota statis tidak diizinkan.

  • Jenis yang digunakan sebagai properti, parameter metode, atau nilai pengembalian hanya dapat berupa jenis Windows Runtime; ini termasuk jenis dasar dan jenis kelas enum.

Deklarasi dan penggunaan

Contoh berikut menunjukkan cara mendeklarasikan antarmuka. Perhatikan bahwa antarmuka dapat dideklarasikan sebagai kelas atau jenis struktur.

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

Untuk mengimplementasikan antarmuka, kelas ref atau struktur ref mendeklarasikan dan mengimplementasikan metode dan properti virtual. Antarmuka dan kelas ref penerapan harus menggunakan nama parameter metode yang sama, seperti yang ditunjukkan dalam contoh ini:

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

Hierarki pewarisan antarmuka

Antarmuka dapat mewarisi dari satu atau beberapa antarmuka. Tetapi tidak seperti kelas ref atau struct, antarmuka tidak mendeklarasikan anggota antarmuka yang diwariskan. Jika antarmuka B mewarisi dari antarmuka A, dan kelas ref C mewarisi dari B, C harus mengimplementasikan A dan B. Ini ditunjukkan dalam contoh berikutnya.

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(){}
};


Menerapkan properti antarmuka dan peristiwa

Seperti yang ditunjukkan pada contoh sebelumnya, Anda dapat menggunakan properti virtual sepele untuk menerapkan properti antarmuka. Anda juga dapat menyediakan getter dan setter kustom di kelas penerapan. Baik getter maupun setter harus publik dalam properti antarmuka.

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

Jika antarmuka mendeklarasikan properti get-only atau set-only, maka kelas penerapan harus secara eksplisit menyediakan getter atau setter.

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

Anda juga dapat menerapkan metode penambahan dan penghapusan kustom untuk peristiwa di kelas penerapan.

Implementasi antarmuka eksplisit

Ketika kelas ref mengimplementasikan beberapa antarmuka, dan antarmuka tersebut memiliki metode yang nama dan tanda tangannya identik dengan pengkompilasi, Anda dapat menggunakan sintaks berikut untuk secara eksplisit menunjukkan metode antarmuka yang diterapkan metode kelas.

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

Antarmuka generik

Di C++/CX, generic kata kunci digunakan untuk mewakili jenis parameter Windows Runtime. Jenis parameter dipancarkan dalam metadata dan dapat dikonsumsi oleh kode yang ditulis dalam bahasa apa pun yang mendukung parameter jenis. Windows Runtime mendefinisikan beberapa antarmuka generik—misalnya, Windows::Foundation::Collections::IVector<T>—tetapi tidak mendukung pembuatan antarmuka generik yang ditentukan pengguna publik di C++/CX. Namun, Anda dapat membuat antarmuka generik privat.

Berikut adalah cara jenis Windows Runtime dapat digunakan untuk menulis antarmuka generik:

  • Pengguna generik yang ditentukan interface class dalam komponen tidak diizinkan untuk dipancarkan ke dalam file metadata Windows-nya; oleh karena itu, tidak dapat memiliki aksesibilitas publik, dan kode klien dalam file .winmd lainnya tidak dapat mengimplementasikannya. Ini dapat diimplementasikan oleh kelas ref non-publik dalam komponen yang sama. Kelas ref publik dapat memiliki jenis antarmuka generik sebagai anggota privat.

    Cuplikan kode berikut menunjukkan cara mendeklarasikan generik interface class dan kemudian mengimplementasikannya di kelas ref privat dan menggunakan kelas ref sebagai anggota privat di kelas ref publik.

    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;
    
    };
    
  • Antarmuka generik harus mengikuti aturan antarmuka standar yang mengatur aksesibilitas, anggota, memerlukan hubungan, kelas dasar, dan sebagainya.

  • Antarmuka generik dapat mengambil satu atau beberapa parameter jenis generik yang didahului oleh typename atau class. Parameter non-jenis tidak didukung.

  • Parameter jenis dapat berupa jenis Windows Runtime apa pun. Artinya, parameter jenis dapat berupa jenis referensi, jenis nilai, kelas antarmuka, delegasi, jenis dasar, atau kelas enum publik.

  • Antarmuka generik tertutup adalah antarmuka yang mewarisi dari antarmuka generik dan menentukan argumen jenis konkret untuk semua parameter jenis. Ini dapat digunakan di mana saja bahwa antarmuka privat non-generik dapat digunakan.

  • Antarmuka generik terbuka adalah antarmuka yang memiliki satu atau beberapa parameter jenis yang belum disediakan jenis beton. Ini dapat digunakan di mana saja bahwa jenis dapat digunakan, termasuk sebagai argumen jenis antarmuka generik lainnya.

  • Anda hanya dapat membuat parameter seluruh antarmuka, bukan metode individual.

  • Parameter jenis tidak dapat dibatasi.

  • Antarmuka generik tertutup memiliki UUID yang dihasilkan secara implisit. Pengguna tidak dapat menentukan UUID.

  • Di antarmuka, referensi apa pun ke antarmuka saat ini—dalam parameter metode, nilai pengembalian, atau properti—diasumsikan untuk merujuk ke instansiasi saat ini. Misalnya, IMyIntf berarti IMyIntf<T>.

  • Ketika jenis parameter metode adalah parameter jenis, deklarasi parameter atau variabel tersebut menggunakan nama parameter jenis tanpa pointer, referensi asli, atau menangani deklarator. Dengan kata lain, Anda tidak pernah menulis "T^".

  • Kelas ref yang di-template harus bersifat privat. Mereka dapat menerapkan antarmuka generik, dan dapat meneruskan parameter templat T ke argumen generik T. Setiap instansiasi kelas ref yang di-template adalah kelas ref.

Lihat juga

Sistem Jenis
Referensi Bahasa C++/CX
Referensi Namespace