Delegasi vs Antarmuka - Ada klarifikasi lain yang tersedia?


23

Setelah membaca artikel - Kapan Menggunakan Delegasi Bukan Antarmuka (Panduan Pemrograman C #) , saya butuh bantuan untuk memahami poin-poin di bawah ini, yang saya temukan tidak begitu jelas (untuk saya). Adakah contoh atau penjelasan terperinci yang tersedia untuk ini?

Gunakan delegasi ketika:

  • Pola desain acara digunakan.
  • Sangat diinginkan untuk merangkum metode statis.
  • Komposisi yang mudah diinginkan.
  • Kelas mungkin membutuhkan lebih dari satu implementasi metode.

Gunakan antarmuka saat:

  • Ada sekelompok metode terkait yang dapat dipanggil.
  • Kelas hanya membutuhkan satu implementasi metode.

Pertanyaan saya adalah,

  1. Apa yang mereka maksud dengan pola desain acara?
  2. Bagaimana komposisi ini menjadi mudah jika delegasi digunakan?
  3. jika ada sekelompok metode terkait yang dapat dipanggil, maka gunakan antarmuka-Apa manfaatnya?
  4. jika sebuah kelas hanya membutuhkan satu implementasi dari metode ini, gunakan antarmuka-bagaimana itu dibenarkan dalam hal manfaat?

Jawaban:


11

Apa yang mereka maksud dengan pola desain acara?

Mereka kemungkinan besar merujuk pada implementasi dari pola pengamat yang merupakan konstruksi bahasa inti dalam C #, diekspos sebagai ' peristiwa '. Mendengarkan acara dimungkinkan dengan mengaitkan seorang delegasi dengan mereka. Seperti yang ditunjukkan Yam Marcovic, EventHandleradalah tipe delegasi basis konvensional untuk acara, tetapi tipe delegasi apa pun dapat digunakan.

Bagaimana komposisi ini menjadi mudah jika delegasi digunakan?

Ini mungkin hanya merujuk pada tawaran delegasi fleksibilitas. Anda dapat dengan mudah 'menciptakan' perilaku tertentu. Dengan bantuan lambdas , sintaksis untuk melakukan ini juga sangat ringkas. Perhatikan contoh berikut.

class Bunny
{
    Func<bool> _canHop;

    public Bunny( Func<bool> canHop )
    {
        _canHop = canHop;
    }

    public void Hop()
    {
        if ( _canHop() )  Console.WriteLine( "Hop!" );
    }
}

Bunny captiveBunny = new Bunny( () => IsBunnyReleased );
Bunny lazyBunny = new Bunny( () => !IsLazyDay );
Bunny captiveLazyBunny = new Bunny( () => IsBunnyReleased && !IsLazyDay );

Melakukan sesuatu yang mirip dengan antarmuka akan mengharuskan Anda untuk menggunakan pola strategi atau menggunakan Bunnykelas dasar (abstrak) dari mana Anda memperluas kelinci yang lebih spesifik.

jika ada sekelompok metode terkait yang dapat dipanggil, maka gunakan antarmuka-Apa manfaatnya?

Sekali lagi, saya akan menggunakan kelinci untuk menunjukkan bagaimana itu akan lebih mudah.

interface IAnimal
{
    void Jump();
    void Eat();
    void Poo();
}

class Bunny : IAnimal { ... }
class Chick : IAnimal { ... }

// Using the interface.
IAnimal bunny = new Bunny();
bunny.Jump();  bunny.Eat();  bunny.Poo();
IAnimal chick = new Chick();
chick.Jump();  chick.Eat();  chick.Poo();

// Without the interface.
Action bunnyJump = () => bunny.Jump();
Action bunnyEat = () => bunny.Eat();
Action bunnyPoo = () => bunny.Poo();
bunnyJump(); bunnyEat(); bunnyPoo();
Action chickJump = () => chick.Jump();
Action chickEat = () => chick.Eat();
...

jika sebuah kelas hanya membutuhkan satu implementasi dari metode ini, gunakan antarmuka-bagaimana itu dibenarkan dalam hal manfaat?

Untuk ini, perhatikan contoh pertama dengan kelinci lagi. Jika hanya satu implementasi yang diperlukan - tidak ada komposisi khusus yang diperlukan -, Anda dapat mengekspos perilaku ini sebagai antarmuka. Anda tidak perlu membangun lambdas, Anda hanya dapat menggunakan antarmuka.

Kesimpulan

Delegasi menawarkan lebih banyak fleksibilitas, sementara antarmuka membantu Anda membuat kontrak yang kuat. Oleh karena itu saya menemukan poin terakhir yang disebutkan, "Kelas mungkin membutuhkan lebih dari satu implementasi metode." , sejauh ini yang paling relevan.

Alasan tambahan kapan harus menggunakan delegasi adalah ketika Anda ingin mengekspos hanya bagian dari kelas yang tidak dapat Anda sesuaikan dengan file sumbernya.

Sebagai contoh skenario seperti itu (fleksibilitas maksimum, tidak perlu memodifikasi sumber), pertimbangkan penerapan algoritma pencarian biner ini untuk kemungkinan pengumpulan dengan hanya melewati dua delegasi.


12

Delegasi adalah sesuatu seperti antarmuka untuk tanda tangan metode tunggal, yang tidak harus diimplementasikan secara eksplisit seperti antarmuka biasa. Anda dapat membuatnya saat dijalankan.

Antarmuka hanyalah struktur bahasa yang mewakili beberapa kontrak - "Saya dengan ini menjamin saya membuat metode dan properti berikut tersedia".

Juga, saya tidak sepenuhnya setuju bahwa delegasi terutama berguna ketika digunakan sebagai solusi untuk pola pengamat / pelanggan. Namun, ini adalah solusi elegan untuk "masalah verbositas java".

Untuk pertanyaan Anda:

1 & 2)

Jika Anda ingin membuat sistem acara di Jawa, Anda biasanya menggunakan antarmuka untuk menyebarkan acara, seperti:

interface KeyboardListener
{
    void KeyDown(int key);
    void KeyUp(int key)
    void KeyPress(int key);
    .... and so on
}

Ini berarti kelas Anda harus secara eksplisit mengimplementasikan semua metode ini, dan memberikan stubs untuk semuanya bahkan jika Anda hanya ingin menerapkannya KeyPress(int key).

Di C #, acara ini akan direpresentasikan sebagai daftar delegasi, disembunyikan oleh kata kunci "event" di c #, satu untuk setiap acara tunggal. Ini berarti Anda dapat dengan mudah berlangganan apa yang Anda inginkan tanpa membebani kelas Anda dengan metode "Kunci" publik, dll.

+1 untuk poin 3-5.

Selain itu:

Delegasi sangat berguna ketika Anda ingin menyediakan misalnya fungsi "peta", yang mengambil daftar dan memproyeksikan setiap elemen ke daftar baru, dengan jumlah elemen yang sama, tetapi berbeda dalam beberapa hal. Intinya, IEnumerable. Pilih (...).

IEnumerable.Pilih mengambil Func<TSource, TDest>, yang merupakan delegasi yang membungkus fungsi yang mengambil elemen TSource dan mengubah elemen itu menjadi elemen TDest.

Di Jawa ini harus diimplementasikan menggunakan antarmuka. Seringkali tidak ada tempat alami untuk mengimplementasikan antarmuka semacam itu. Jika suatu kelas berisi daftar yang ingin diubah dengan cara tertentu, tidaklah wajar jika ia mengimplementasikan antarmuka "ListTransformer", terutama karena mungkin ada dua daftar berbeda yang harus diubah dengan cara yang berbeda.

Tentu saja, Anda bisa menggunakan kelas anonim yang merupakan konsep serupa (dalam java).


Pertimbangkan untuk mengedit posting Anda untuk benar-benar menjawab pertanyaannya
Yam Marcovic

@YamMarcovic Anda benar, saya sedikit mengoceh dalam bentuk yang unik, bukannya langsung menjawab pertanyaannya. Namun, saya pikir ini menjelaskan sedikit tentang mekanisme yang terlibat. Selain itu, pertanyaannya agak kurang baik ketika saya menjawab pertanyaan itu. : p
Max

Tentu saja. Terjadi pada saya juga, dan itu memang memiliki nilainya per se. Itu sebabnya saya hanya menyarankannya , tetapi tidak mengeluh. :)
Yam Marcovic

3

1) Pola acara, yah klasiknya adalah pola Pengamat, inilah tautan Microsoft yang bagus Pengamat bicara Microsoft

Artikel yang Anda tautkan tidak ditulis dengan sangat baik dan membuat hal-hal lebih rumit daripada yang diperlukan. Bisnis statis adalah akal sehat, Anda tidak dapat mendefinisikan antarmuka dengan anggota statis, jadi jika Anda ingin perilaku polimorfik pada metode statis, Anda akan menggunakan delegasi.

Tautan di atas berbicara tentang delegasi dan mengapa ada komposisi yang bagus, sehingga dapat membantu dengan permintaan Anda.


3

Pertama-tama, pertanyaan yang bagus. Saya mengagumi fokus Anda pada utilitas daripada menerima "praktik terbaik" secara membuta. +1 untuk itu.

Saya sudah membaca panduan itu sebelumnya. Anda harus mengingat sesuatu tentang hal itu - itu hanya panduan, terutama untuk pendatang C # yang tahu cara memprogram tetapi tidak begitu akrab dengan cara C # dalam melakukan sesuatu. Ini bukan halaman aturan, melainkan halaman yang menjelaskan bagaimana hal-hal sudah biasa dilakukan. Dan karena mereka sudah melakukan hal ini di mana-mana, mungkin ide yang bagus untuk tetap konsisten.

Saya akan langsung ke intinya, menjawab pertanyaan Anda.

Pertama-tama, saya anggap Anda sudah tahu apa antarmuka itu. Adapun delegasi, itu cukup untuk mengatakan bahwa itu adalah struktur yang mengandung pointer yang diketik ke metode, bersama dengan pointer opsional ke objek yang mewakili thisargumen untuk metode itu. Dalam hal metode statis, penunjuk terakhir adalah nol.
Ada juga delegasi Multicast, yang sama seperti delegasi, tetapi mungkin memiliki beberapa struktur yang ditugaskan untuk mereka (artinya panggilan tunggal untuk Memohon pada delegasi multicast memanggil semua metode dalam daftar permintaan yang ditugaskan).

Apa yang mereka maksud dengan pola desain acara?

Maksudnya menggunakan acara dalam C # (yang memiliki kata kunci khusus untuk menerapkan pola yang sangat berguna ini dengan canggih). Acara di C # didorong oleh delegasi multicast.

Saat Anda menentukan suatu peristiwa, seperti dalam contoh ini:

class MyClass {
  // Note: EventHandler is just a multicast delegate,
  // that returns void and accepts (object sender, EventArgs e)!
  public event EventHandler MyEvent;

  public void DoSomethingThatTriggersMyEvent() {
    // ... some code
    var handler = MyEvent;
    if (handler != null)
      handler(this, EventArgs.Empty);
    // ... some other code
  }
}

Compiler sebenarnya mengubah ini menjadi kode berikut:

class MyClass {
  private EventHandler MyEvent = null;

  public void add_MyEvent(EventHandler value) {
    MyEvent += value;
  }

  public void remove_MyEvent(EventHandler value) {
    MyEvent -= value;
  }

  public void DoSomethingThatTriggersMyEvent() {
    // ... some code
    var handler = MyEvent;
    if (handler != null)
      handler(this, EventArgs.Empty);
    // ... some other code
  }
}

Anda kemudian berlangganan ke suatu acara dengan melakukan

MyClass instance = new MyClass();
instance.MyEvent += SomeMethodInMyClass;

Yang mengkompilasi ke

MyClass instance = new MyClass();
instance.add_MyEvent(new EventHandler(SomeMethodInMyClass));

Jadi itu terjadi di C # (atau. NET secara umum).

Bagaimana komposisi ini menjadi mudah jika delegasi digunakan?

Ini dapat dengan mudah ditunjukkan:

Misalkan Anda memiliki kelas yang bergantung pada serangkaian tindakan yang akan diteruskan ke sana. Anda bisa merangkum tindakan-tindakan itu dalam sebuah antarmuka:

interface RequiredMethods {
  void DoX();
  int DoY();
};

Dan siapa pun yang ingin memberikan tindakan ke kelas Anda pertama-tama harus mengimplementasikan antarmuka itu. Atau Anda bisa membuat hidup mereka lebih mudah dengan bergantung pada kelas berikut:

sealed class RequiredMethods {
  public Action DoX;
  public Func<int> DoY();
}

Dengan cara ini, penelepon hanya perlu membuat instance dari RequiredMethods dan mengikat metode kepada delegasi saat runtime. Ini adalah biasanya lebih mudah.

Cara melakukan hal-hal ini sangat bermanfaat dalam keadaan yang tepat. Pikirkan tentang hal ini - mengapa bergantung pada antarmuka saat semua yang Anda benar-benar pedulikan adalah penerapannya diberikan kepada Anda?

Manfaat menggunakan antarmuka saat ada sekelompok metode terkait

Ini bermanfaat untuk menggunakan antarmuka karena antarmuka biasanya memerlukan implementasi waktu kompilasi eksplisit. Ini artinya Anda membuat kelas baru.
Dan jika Anda memiliki sekelompok metode terkait dalam satu paket, sebaiknya paket itu dapat digunakan kembali oleh bagian lain dari kode. Jadi jika mereka dapat membuat instantiate sebuah kelas daripada membangun sekumpulan delegasi, itu lebih mudah.

Manfaat menggunakan antarmuka jika suatu kelas hanya membutuhkan satu implementasi

Seperti disebutkan sebelumnya, antarmuka diimplementasikan dalam waktu kompilasi - yang berarti mereka lebih efisien daripada memanggil delegasi (yang merupakan tingkat tipuan per se).

"Satu implementasi" mungkin berarti implementasi yang ada di satu tempat yang terdefinisi dengan baik.
Kalau tidak, suatu implementasi mungkin datang dari mana saja dalam program yang kebetulan sesuai dengan metode tanda tangan. Itu memungkinkan lebih banyak fleksibilitas, karena metode hanya perlu menyesuaikan diri dengan tanda tangan yang diharapkan, daripada menjadi bagian dari kelas yang secara eksplisit mengimplementasikan antarmuka tertentu. Tetapi fleksibilitas itu mungkin harus dibayar mahal, dan benar-benar melanggar prinsip Pergantian Liskov , karena seringkali Anda menginginkan kesaksian, karena meminimalkan peluang terjadinya kecelakaan. Sama seperti Pengetikan Statis.

Istilah ini juga merujuk pada delegasi multicast di sini. Metode yang dideklarasikan oleh antarmuka hanya dapat diimplementasikan satu kali dalam kelas pelaksana. Tetapi delegasi dapat mengakumulasikan banyak metode, yang akan dipanggil secara berurutan.

Jadi semuanya, sepertinya panduan ini tidak cukup informatif, dan hanya berfungsi seperti apa - panduan, bukan buku aturan. Beberapa saran mungkin terdengar agak kontradiktif. Terserah Anda untuk memutuskan kapan tepat untuk menerapkan apa. Panduan ini sepertinya hanya memberi kita jalan umum.

Saya harap pertanyaan Anda telah dijawab untuk kepuasan Anda. Dan sekali lagi, pujian untuk pertanyaan itu.


2

Jika memori saya. NET masih berlaku, delegasi pada dasarnya adalah ptr fungsi atau functor. Itu menambahkan lapisan tipuan ke panggilan fungsi sehingga fungsi dapat diganti tanpa kode panggilan harus berubah. Ini adalah hal yang sama dengan antarmuka, kecuali bahwa suatu paket memaketkan beberapa fungsi secara bersamaan, dan seorang implementor harus mengimplementasikannya bersama-sama.

Pola acara, secara umum, adalah pola di mana sesuatu merespons peristiwa dari tempat lain (seperti pesan Windows). Serangkaian acara biasanya berakhir terbuka, mereka dapat datang dalam urutan apa pun, dan tidak harus saling terkait. Delegasi bekerja dengan baik untuk ini di mana setiap peristiwa dapat memanggil fungsi tunggal tanpa perlu referensi ke serangkaian objek implementasi yang mungkin juga mengandung banyak fungsi yang tidak relevan. Selain itu (ini adalah di mana memori .NET saya tidak jelas), saya pikir beberapa delegasi dapat dilampirkan ke suatu acara.

Pengomposisian, meskipun saya tidak terlalu mengenal istilah ini, pada dasarnya mendesain satu objek untuk memiliki beberapa sub-bagian, atau anak-anak agregat yang pekerjaannya diturunkan. Delegasi memungkinkan anak-anak untuk dicampur dan dicocokkan dengan cara yang lebih ad-hoc di mana antarmuka mungkin berlebihan atau menyebabkan terlalu banyak kopling dan kekakuan dan kerapuhan yang menyertainya.

Manfaat antarmuka untuk metode terkait adalah bahwa metode tersebut dapat berbagi keadaan objek pelaksana. Mendelegasikan fungsi tidak dapat membagikan, atau bahkan memuat, dengan rapi.

Jika suatu kelas membutuhkan implementasi tunggal, sebuah antarmuka lebih cocok karena di dalam setiap kelas yang mengimplementasikan seluruh koleksi, hanya satu implementasi yang dapat dilakukan, dan Anda mendapatkan manfaat dari kelas pelaksana (negara, enkapsulasi, dll.). Jika implementasi mungkin berubah karena keadaan runtime, delegasi bekerja lebih baik karena mereka dapat ditukar dengan implementasi lain tanpa mempengaruhi metode lain. Misalnya, jika ada tiga delegasi yang masing-masing memiliki dua implementasi yang mungkin, Anda akan membutuhkan delapan kelas yang berbeda mengimplementasikan antarmuka tiga metode untuk menjelaskan semua kemungkinan kombinasi negara.


1

Pola desain "acara" (lebih dikenal sebagai Pola Pengamat) memungkinkan Anda untuk melampirkan beberapa metode tanda tangan yang sama ke delegasi. Anda tidak dapat melakukannya dengan antarmuka.

Saya sama sekali tidak yakin bahwa komposisi lebih mudah untuk delegasi daripada antarmuka. Itu pernyataan yang sangat aneh. Saya ingin tahu apakah maksudnya karena Anda dapat melampirkan metode anonim ke delegasi.


1

Klarifikasi terbesar yang dapat saya tawarkan:

  1. Delegasi mendefinisikan tanda tangan fungsi - parameter mana yang akan diterima fungsi pencocokan dan apa yang akan dikembalikan.
  2. Antarmuka berhubungan dengan seluruh rangkaian fungsi, acara, properti, dan bidang.

Begitu:

  1. Saat Anda ingin menggeneralisasi beberapa fungsi dengan tanda tangan yang sama - gunakan delegasi.
  2. Saat Anda ingin menggeneralisasi beberapa perilaku atau kualitas kelas - gunakan antarmuka.

1

Pertanyaan Anda tentang acara telah dibahas dengan baik. Dan juga benar, bahwa sebuah antarmuka dapat mendefinisikan beberapa metode (tetapi sebenarnya tidak perlu), sementara tipe fungsi hanya pernah menempatkan kendala pada fungsi individu.

Perbedaan sesungguhnya adalah:

  • nilai-nilai fungsi dicocokkan dengan tipe-tipe fungsi dengan subtyping struktural (yaitu kompatibilitas implisit dengan struktur yang diminta). Itu berarti, jika nilai fungsi memiliki tanda tangan yang kompatibel dengan tipe fungsi, itu adalah nilai yang valid untuk tipe tersebut.
  • instance dicocokkan dengan antarmuka dengan subtyping nominal (yaitu penggunaan nama secara eksplisit). Itu berarti, jika sebuah instance adalah anggota kelas, yang secara eksplisit mengimplementasikan antarmuka yang diberikan, instance tersebut adalah nilai yang valid untuk antarmuka tersebut. Namun, jika objek hanya memiliki semua anggota yang diminta oleh antarmuka, dan semua anggota memiliki tanda tangan yang kompatibel, tetapi tidak secara eksplisit mengimplementasikan antarmuka, itu bukan nilai yang valid untuk antarmuka.

Tentu, tapi apa artinya ini?

Mari kita ambil contoh ini (kode dalam haXe karena C # saya tidak terlalu baik):

class Collection<T> {
    /* a lot of code we don't care about now */
    public function filter(predicate:T->Bool):Collection<T> { 
         //build a new collection with all elements e, such that predicate(e) == true
    }
    public function remove(e:T):Bool {
         //removes an element from this collection, if contained and returns true, false otherwise
    }
}

Sekarang metode filter memudahkan untuk dengan mudah melewati hanya sepotong kecil logika, yang tidak mengetahui organisasi internal koleksi, sedangkan koleksi tidak bergantung pada logika yang diberikan kepadanya. Besar. Kecuali untuk satu masalah:
Koleksi tidak bergantung pada logika. Koleksi secara inheren membuat asumsi, bahwa fungsi yang diteruskan dirancang untuk menguji nilai terhadap suatu kondisi dan mengembalikan keberhasilan tes. Perhatikan bahwa tidak semua fungsi, yang mengambil satu nilai sebagai argumen dan mengembalikan boolean sebenarnya hanyalah predikat. Misalnya metode hapus koleksi kami adalah fungsi seperti itu.
Anggaplah kita menelepon c.filter(c.remove). Hasilnya akan menjadi koleksi dengan semua elemen csementaracitu sendiri menjadi kosong. Ini sangat disayangkan, karena secara alami kita akan mengharapkan cdirinya menjadi invarian.

Contohnya sangat dibangun. Tetapi masalah utama adalah, bahwa pemanggilan kode c.filterdengan beberapa nilai fungsi sebagai argumen tidak memiliki cara untuk mengetahui apakah argumen itu cocok (yaitu pada akhirnya akan menghemat invarian). Kode yang menciptakan nilai fungsi mungkin atau mungkin tidak tahu, bahwa itu akan ditafsirkan sebagai predikat.

Sekarang mari kita ubah beberapa hal:

interface Predicate<T> {
    function test(value:T):Bool;
}
class Collection<T> {
    /* a lot of code we don't care about now */
    public function filter(predicate:Predicate<T>):Collection<T> { 
         //build a new collection with all elements e, such that predicate.test(e) == true
    }
    public function remove(e:T):Bool {
         //removes an element from this collection, if contained and returns true, false otherwise
    }
}

Apa yang sudah berubah? Apa yang telah berubah adalah, bahwa nilai apa pun yang sekarang diberikan filtertelah secara eksplisit menandatangani kontrak menjadi predikat. Tentu saja programmer jahat atau sangat bodoh membuat implementasi dari antarmuka yang tidak bebas efek samping dan karenanya bukan predikat.
Tetapi yang tidak bisa lagi terjadi adalah seseorang mengikat unit logis dari data / kode, yang secara keliru diartikan sebagai predikat karena struktur luarnya.

Jadi ulangi apa yang dikatakan di atas hanya dalam beberapa kata:

  • antarmuka berarti menggunakan pengetikan nominal dan dengan demikian hubungan eksplisit
  • delegasi berarti menggunakan pengetikan struktural dan dengan demikian hubungan implisit

Keuntungan dari hubungan eksplisit adalah, bahwa Anda dapat memastikannya. Kerugiannya adalah, bahwa mereka membutuhkan overhead dari kesederhanaan. Sebaliknya, kerugian dari hubungan implisit (dalam kasus kami satu fungsi tanda tangan cocok dengan tanda tangan yang diinginkan), adalah bahwa Anda tidak dapat benar-benar 100% yakin bahwa Anda dapat menggunakan sesuatu dengan cara ini. Keuntungannya adalah, Anda bisa menjalin hubungan tanpa semua overhead. Anda dapat dengan cepat melempar barang-barang bersama, karena struktur mereka memungkinkan. Itulah yang dimaksud komposisi mudah.
Ini agak seperti LEGO: Anda dapat dengan mudah memasang figur star wars LEGO ke kapal bajak laut LEGO, hanya karena struktur luar memungkinkannya. Sekarang Anda mungkin merasa itu sangat salah, atau mungkin persis seperti yang Anda inginkan. Tidak ada yang akan menghentikan Anda.


1
Perlu disebutkan bahwa "secara eksplisit mengimplementasikan antarmuka" (di bawah "subtyping nominal") tidak sama dengan implementasi eksplisit atau implisit anggota antarmuka. Di C #, kelas harus selalu secara eksplisit mendeklarasikan antarmuka yang mereka implementasikan, seperti yang Anda katakan. Tetapi anggota antarmuka dapat diimplementasikan baik secara eksplisit (misalnya, int IList.Count { get { ... } }) atau secara implisit ( public int Count { get { ... } }). Perbedaan ini tidak relevan dengan diskusi ini, tetapi patut disebutkan untuk menghindari pembaca yang membingungkan.
phoog

@phoog: Ya, terima kasih atas amandemennya. Aku bahkan tidak tahu yang pertama mungkin. Tapi ya, cara bagaimana suatu bahasa benar-benar menegakkan implementasi antarmuka sangat bervariasi. Di Objective-C misalnya, itu hanya akan memberi Anda peringatan jika tidak diterapkan.
back2dos

1
  1. Pola desain acara menyiratkan struktur yang melibatkan mekanisme publikasi dan berlangganan. Acara diterbitkan oleh sumber, setiap pelanggan mendapatkan salinannya sendiri dari item yang diterbitkan dan bertanggung jawab atas tindakannya sendiri. Itu adalah mekanisme yang digabungkan secara longgar karena penerbit bahkan tidak perlu tahu pelanggan ada di sana. Apalagi memiliki pelanggan tidak wajib (tidak ada)
  2. Komposisi "lebih mudah" jika delegasi digunakan dibandingkan dengan antarmuka. Antarmuka mendefinisikan instance kelas sebagai objek "semacam handler" di mana sebagai instance konstruksi komposisi tampak "memiliki handler" oleh karena itu penampilan instance kurang dibatasi dengan menggunakan delegasi dan menjadi lebih fleksibel.
  3. Dari komentar di bawah ini saya menemukan bahwa saya perlu memperbaiki posting saya, lihat ini untuk referensi: http://bytes.com/topic/c-sharp/answers/252309-interface-vs-delegate

1
3. Mengapa delegasi membutuhkan lebih banyak casting, dan mengapa lebih ketat menggabungkan manfaat? 4. Anda tidak harus menggunakan acara untuk menggunakan delegasi, dan dengan delegasi itu seperti memegang metode - Anda tahu itu tipe pengembalian dan itu jenis argumen. Juga, mengapa metode yang dideklarasikan dalam antarmuka membuatnya lebih mudah untuk menangani kesalahan daripada metode yang dilampirkan pada delegasi?
Yam Marcovic

Dalam hal hanya spesifikasi delegasi Anda benar. Namun dalam hal penanganan acara (setidaknya itulah yang menjadi rujukan referensi saya), Anda selalu harus mewarisi bentuk semacam eventArgs untuk bertindak sebagai wadah untuk jenis kustom, jadi alih-alih dapat dengan aman menguji nilai yang Anda akan selalu harus membuka bungkusan jenis Anda sebelum menangani nilai-nilai.
Carlo Kuip

Adapun alasan mengapa saya pikir metode yang didefinisikan dalam suatu antarmuka akan membuatnya lebih mudah untuk menangani kesalahan adalah memiliki kompiler yang dapat memeriksa jenis pengecualian yang dilemparkan dari metode itu. Saya tahu ini bukan bukti yang meyakinkan tetapi mungkin harus dinyatakan sebagai preferensi?
Carlo Kuip

1
Pertama kami berbicara tentang delegasi vs antarmuka, bukan peristiwa vs antarmuka. Kedua, membuat acara berdasarkan pada delegasi EventHandler hanyalah sebuah konvensi, dan sama sekali tidak wajib. Tetapi sekali lagi, berbicara tentang peristiwa di sini agak melenceng. Adapun komentar kedua Anda - pengecualian tidak dicentang dalam C #. Anda menjadi bingung dengan Java (yang notabene bahkan tidak memiliki delegasi).
Yam Marcovic

Menemukan utas tentang hal ini yang menjelaskan perbedaan penting: bytes.com/topic/c-sharp/answers/252309-interface-vs-delegate
Carlo Kuip
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.