Mengapa antarmuka bermanfaat?

158

Saya telah mempelajari dan mengkode dalam C # untuk beberapa waktu sekarang. Tapi tetap saja, saya tidak bisa membayangkan kegunaan Interfaces. Mereka membawa terlalu sedikit ke meja. Selain memberikan tanda tangan fungsi, mereka tidak melakukan apa pun. Jika saya dapat mengingat nama dan tanda tangan dari fungsi-fungsi yang perlu diterapkan, tidak perlu bagi mereka. Mereka ada di sana hanya untuk memastikan bahwa fungsi-fungsi tersebut (di antarmuka) diimplementasikan di kelas pewarisan.

C # adalah bahasa yang hebat, tetapi kadang-kadang memberi Anda perasaan bahwa Microsoft pertama kali menciptakan masalah (tidak mengizinkan banyak warisan) dan kemudian memberikan solusi, yang agak membosankan.

Itulah pemahaman saya yang didasarkan pada pengalaman coding yang terbatas. Apa pendapat Anda tentang antarmuka? Seberapa sering Anda memanfaatkannya dan apa yang membuat Anda melakukannya?

Pankaj Upadhyay
sumber
55
"Jika saya dapat mengingat nama dan tanda tangan dari fungsi yang perlu diterapkan, tidak perlu bagi mereka." Pernyataan ini membuat saya curiga Anda harus melihat sedikit lebih dalam kelebihan dari bahasa yang diketik secara statis .
Steven Jeuris
37
Lupakan C #, lupakan Java, lupakan bahasa. Itu hanya berpikir dalam hal OO. Saya akan mendorong Anda untuk mengambil beberapa bahan bacaan dari orang-orang seperti Robert C. Martin, Martin Fowler, Michael Feathers, Geng Empat, dll., Karena itu akan membantu memperluas pemikiran Anda.
Anthony Pegram
27
Butuh lebih dari dua tahun untuk benar-benar memahami antarmuka apa yang bagus untuk itu. Saran saya: pelajari Pola Desain. Karena kebanyakan dari mereka bergantung pada antarmuka, Anda akan dengan cepat memahami mengapa mereka sangat berguna.
Oliver Weiler
37
Anda punya banyak hal untuk dipelajari teman.
ChaosPandion
60
@ChaosPandion, kita semua harus belajar banyak
kenwarner

Jawaban:

151

Mereka ada di sana hanya untuk memastikan bahwa fungsi-fungsi tersebut (dalam antarmuka) diimplementasikan di kelas pewarisan.

Benar. Itu manfaat yang cukup luar biasa untuk membenarkan fitur tersebut. Seperti yang dikatakan orang lain, antarmuka adalah kewajiban kontraktual untuk mengimplementasikan metode, properti, dan acara tertentu. Manfaat menarik dari bahasa yang diketik secara statis adalah bahwa kompiler dapat memverifikasi bahwa kontrak yang diandalkan oleh kode Anda benar-benar terpenuhi.

Yang mengatakan, antarmuka adalah cara yang cukup lemah untuk mewakili kewajiban kontrak. Jika Anda ingin cara yang lebih kuat dan lebih fleksibel untuk mewakili kewajiban kontrak, lihat fitur Kontrak Kode yang dikirimkan bersama dengan Visual Studio versi terakhir.

C # adalah bahasa yang hebat, tetapi kadang-kadang memberi Anda perasaan bahwa Microsoft pertama kali menciptakan masalah (tidak mengizinkan multiple inheritance) dan kemudian memberikan solusinya, yang agak membosankan.

Yah aku senang kamu menyukainya.

Semua desain perangkat lunak yang kompleks adalah hasil dari menimbang fitur yang saling bertentangan satu sama lain, dan berusaha menemukan "sweet spot" yang memberikan manfaat besar dengan biaya kecil. Kami telah belajar dari pengalaman yang menyakitkan bahwa bahasa yang memungkinkan pewarisan berganda untuk tujuan berbagi implementasi memiliki manfaat yang relatif kecil dan biaya yang relatif besar. Mengijinkan multiple inheritance hanya pada interface, yang tidak membagikan detail implementasi, memberikan banyak manfaat multiple inheritance tanpa sebagian besar biaya.

Eric Lippert
sumber
Saya baru saja membaca "Microsoft menciptakan masalah dengan tidak mengizinkan multiple inheritance" dan saya pikir Eric Lippert akan mengatakan sesuatu tentang itu.
konfigurator
Lebih relevan dengan jawaban ini: Eric, Anda merujuk si penanya ke Kontrak Kode, tetapi sayangnya tidak lengkap; apa pun selain kontrak paling dasar tidak dapat diberlakukan oleh pemeriksa statis. Saya mencoba menggunakan Kontrak Kode pada proyek kecil; Saya telah menambahkan ratusan baris untuk masing-masing dan setiap metode yang menetapkan segala yang saya bisa tentang input dan output, namun, saya harus menambahkan begitu banyak Assumepanggilan, untuk kasus seperti array atau enumerasi anggota. Setelah menambahkan semuanya dan melihat kekacauan yang diverifikasi secara statis yang saya miliki, saya kembali dalam kontrol sumber karena mengurangi kualitas proyek saya.
konfigurator
17
@configurator: Tidak lengkap karena tidak bisa lengkap; verifikasi program statis dengan kontrak sewenang-wenang setara dengan menyelesaikan Masalah Henti. (Misalnya, Anda dapat menulis kontrak kode yang mengatakan bahwa argumen untuk suatu metode harus merupakan contoh tandingan terhadap Teorema Terakhir Fermat; tetapi verifikasi statis tidak akan dapat memverifikasi bahwa tidak ada argumen seperti itu.) Anda sudah harus menggunakannya dengan bijaksana jika Anda mengharapkan verifier statis untuk menyelesaikan pekerjaannya sebelum kematian panas alam semesta. (Jika keluhan Anda adalah bahwa BCL tidak cukup beranotasi: Saya setuju.)
Eric Lippert
2
Saya berharap untuk menyadari bahwa ketika satu metode menjanjikan bahwa hasil array atau enumerasi tidak mengandung nol, metode menggunakan dapat menggunakan nilai-nilai di tempat-tempat yang tidak mengizinkan nol. Itulah satu hal yang saya harapkan tidak terjadi, dan terlalu penting untuk dapat digunakan tanpanya; yang lainnya hanyalah bonus. Yang mengatakan, saya tahu verifikasi statis tidak dapat lengkap, itulah sebabnya saya pikir itu bukan alternatif yang baik untuk mengandalkan kontrak.
konfigurator
9
+1 untuk "Yah, aku senang kamu menyukainya." Dan semua hal lainnya juga.
Robert S.
235

masukkan deskripsi gambar di sini

Jadi dalam contoh ini, PowerSocket tidak tahu apa-apa tentang objek lain. Objek semua tergantung pada Power yang disediakan oleh PowerSocket, sehingga mereka mengimplementasikan IPowerPlug, dan dengan demikian mereka dapat terhubung ke sana.

Antarmuka berguna karena mereka memberikan kontrak yang dapat digunakan benda untuk bekerja bersama tanpa perlu tahu apa pun tentang satu sama lain.

Slomojo
sumber
4
Objek kiri bawah tidak terlihat seperti mengimplementasikan IPowerPlug =)
Steven Striga
100
Sial, tapi kita harus menggunakan pola Adaptor untuk menggunakan IPowerPlug di berbagai negara!
Steven Jeuris
Jerry-mencurangi sebuah alat untuk bekerja di sekitar antarmuka tidak aman (tetapi beberapa orang masih melakukannya sering mengutip kinerja sebagai alasan yang belum teruji), dan kemungkinan menyebabkan kebakaran.
YoungJohn
4
Jawaban ini luar biasa ...
Mario Garcia
Hanya menunjukkan jawaban ini tidak mengatakan - dalam contoh khusus ini - mengapa menggunakan antarmuka lebih disukai daripada warisan. Seseorang yang baru mengenal antarmuka mungkin bertanya mengapa mereka tidak hanya mewarisi dari misalnya MainsPoweredDevice yang menyediakan semua fungsi colokan, dengan soket yang menerima apa pun yang berasal dari MainsPoweredDevice.
ingredient_15939
145

Selain memberikan tanda tangan fungsi, mereka tidak melakukan apa pun. Jika saya dapat mengingat nama dan tanda tangan dari fungsi yang perlu diterapkan, tidak perlu bagi mereka

Titik antarmuka bukan untuk membantu Anda mengingat metode apa yang harus diterapkan, tetapi di sini untuk menentukan kontrak . Dalam P.Brian.Mackey contoh foreach (yang ternyata salah , tapi kami tidak peduli), IEnumerable mendefinisikan kontrak antara foreach dan setiap hal enumerable. Dikatakan: "Siapa pun Anda, selama Anda tetap berpegang pada kontrak (mengimplementasikan IEnumerable), saya berjanji Anda akan beralih pada semua elemen Anda". Dan, itu hebat (untuk bahasa yang tidak dinamis).

Berkat antarmuka Anda dapat mencapai kopling sangat rendah antara dua kelas.

David
sumber
Saya tidak suka menggunakan istilah "mengetik bebek" karena ini berarti hal yang berbeda untuk orang yang berbeda. Kami menggunakan pencocokan pola untuk loop "foreach" karena ketika itu dirancang, IEnumerable <T> tidak tersedia. Kami menggunakan pencocokan pola untuk LINQ karena sistem tipe C # terlalu lemah untuk menangkap "pola monad" yang kami butuhkan; Anda akan membutuhkan sesuatu seperti sistem jenis Haskell.
Eric Lippert
@ Eric: Bukankah "pencocokan pola" memiliki masalah yang sama? Ketika saya mendengarnya, saya pikir F ​​# / Scala / Haskell. Tapi saya kira itu ide yang lebih luas daripada mengetik bebek.
Daniel
@Aniel: Ya, saya kira begitu. Saya kira enam dari satu setengah lusin lainnya!
Eric Lippert
36

Antarmuka adalah cara terbaik untuk mempertahankan konstruksi yang dipisahkan dengan baik.

Saat menulis tes, Anda akan menemukan bahwa kelas konkret tidak akan berfungsi di lingkungan tes Anda.

Contoh: Anda ingin menguji kelas yang bergantung pada kelas Layanan Akses Data . Jika kelas itu berbicara dengan layanan web, atau database - pengujian unit Anda tidak akan berjalan di lingkungan pengujian Anda (ditambah lagi telah berubah menjadi tes integrasi).

Larutan? Gunakan Antarmuka untuk Layanan Akses Data Anda dan Mock antarmuka itu sehingga Anda dapat menguji kelas Anda sebagai satu unit.

Di sisi lain, WPF & Silverlight tidak bermain sama sekali dengan Interfaces ketika datang untuk mengikat. Ini adalah kerutan yang cukup jahat.

Sheldon Warkentin
sumber
2
dengar dengar! Antarmuka diciptakan untuk memecahkan masalah lain, seperti polimorfisme. Namun, bagi saya, mereka menjadi milik mereka sendiri ketika menerapkan pola Injeksi Ketergantungan.
andy
29

Antarmuka adalah tulang punggung polimorfisme (statis)! Antarmuka adalah yang penting. Warisan tidak akan berfungsi tanpa antarmuka, karena subclass pada dasarnya mewarisi antarmuka induk yang sudah diimplementasikan.

Seberapa sering Anda memanfaatkannya dan apa yang membuat Anda melakukannya ??

Cukup sering. Segala sesuatu yang perlu dicolokkan adalah antarmuka dalam aplikasi saya. Seringkali kali Anda memiliki kelas yang tidak terkait yang perlu memberikan perilaku yang sama. Anda tidak dapat memecahkan masalah seperti itu dengan warisan.

Perlu algoritma yang berbeda untuk melakukan operasi pada data yang sama? Gunakan antarmuka ( lihat pola strategi )!

Apakah Anda ingin menggunakan implementasi daftar yang berbeda? Kode terhadap antarmuka dan penelepon tidak perlu khawatir tentang implementasinya!

Sudah dianggap sebagai praktik yang baik (tidak hanya dalam OOP) untuk kode terhadap antarmuka selama berabad-abad, karena satu alasan tunggal: Sangat mudah untuk mengubah implementasi ketika Anda menyadari itu tidak sesuai dengan kebutuhan Anda. Cukup rumit jika Anda mencoba mencapainya hanya dengan banyak pewarisan atau bermuara pada pembuatan kelas kosong untuk menyediakan antarmuka yang diperlukan.

Falcon
sumber
1
Belum pernah mendengar tentang polimorfisme, maksud Anda polimorfisme?
Steven Jeuris
1
yang dikatakan, jika microsoft memungkinkan pewarisan berganda di tempat pertama, tidak akan ada alasan untuk adanya antarmuka
Pankaj Upadhyay
10
@Pankaj Upadhyay: Berbagai warisan dan antarmuka adalah dua pasang sepatu yang berbeda. Bagaimana jika Anda membutuhkan antarmuka dua kelas yang tidak terkait dengan perilaku yang berbeda? Anda tidak dapat menyelesaikannya dengan pewarisan berganda. Anda HARUS mengimplementasikannya secara terpisah. Dan Anda akan membutuhkan sesuatu untuk menggambarkan antarmuka untuk memberikan perilaku polimorfik. Warisan berganda adalah jalan buntu untuk berjalan dalam banyak kasus, dan terlalu mudah untuk menembak diri sendiri cepat atau lambat.
Falcon
1
Mari kita sederhanakan. Jika antarmuka saya mengimplementasikan dua fungsi Tampilan dan Komentar, dan saya memiliki kelas yang mengimplementasikannya. Lalu mengapa saya tidak menghapus antarmuka dan menggunakan fungsi secara langsung. Apa yang saya katakan adalah bahwa mereka hanya memberi Anda nama-nama fungsi yang perlu diterapkan. Jika seseorang dapat mengingat fungsi-fungsi itu maka mengapa membuat antarmuka
Pankaj Upadhyay
9
@ Pankaj, jika hanya itu yang Anda butuhkan untuk antarmuka, maka jangan gunakan itu. Anda menggunakan antarmuka ketika Anda memiliki program yang ingin mengabaikan setiap aspek kelas dan mengaksesnya dengan Tipe dasarnya, yaitu antarmuka. Mereka tidak perlu mengetahui subclass apa pun, hanya saja itu dari jenis antarmuka. Dengan demikian, Anda dapat memanggil metode yang diterapkan dari sub-kelas melalui referensi ke antarmuka objek. Ini adalah barang warisan dan desain dasar. Tanpa itu, Anda mungkin juga menggunakan C. Bahkan jika Anda tidak menggunakannya secara eksplisit, framework tidak akan berfungsi tanpanya.
Jonathan Henson
12

Anda mungkin telah menggunakan foreachdan menemukannya sebagai alat iterasi yang cukup berguna. Tahukah Anda bahwa itu membutuhkan antarmuka untuk berfungsi, IEnumerable ?

Itu tentu kasus konkret berbicara tentang kegunaan antarmuka.

P.Brian.Mackey
sumber
5
Sebenarnya, foreach tidak memerlukan IEnumerable: msdn.microsoft.com/en-us/library/9yb8xew9%28VS.80%29.aspx
Matt H
1
Saya telah mempelajari semua itu tetapi itu seperti memegang telinga dengan tangan lain. Jika beberapa pewarisan diizinkan, antarmuka akan menjadi pilihan yang jauh.
Pankaj Upadhyay
2
Antarmuka ADALAH pewarisan berganda, sesuatu yang sering dilupakan. Namun, mereka tidak memungkinkan pewarisan berganda perilaku dan negara. Mixin atau sifat memungkinkan pewarisan berganda perilaku, tetapi tidak berbagi keadaan yang menyebabkan masalah: en.wikipedia.org/wiki/Mixin
Matt H
@ Pankaj, offtopic, tetapi apakah Anda keberatan jika saya bertanya apa bahasa ibu Anda? "Memegang telinganya dengan tangan lain" adalah ungkapan yang bagus dan saya ingin tahu dari mana asalnya.
Kevin
3
@Tukang es. LOL .... Saya dari india. Dan ini adalah ungkapan umum yang mencerminkan melakukan hal-hal mudah dengan cara yang sulit.
Pankaj Upadhyay
11

Antarmuka adalah untuk pengkodean objek seperti steker ke kabel rumah tangga. Apakah Anda menyolder radio Anda langsung ke kabel rumah Anda? Bagaimana dengan penyedot debu Anda? Tentu saja tidak. Steker, dan stopkontak yang cocok, membentuk "antarmuka" antara kabel rumah Anda dan perangkat yang membutuhkan daya dari itu. Kabel rumah Anda tidak perlu tahu apa-apa tentang perangkat selain menggunakan steker ground tiga cabang dan membutuhkan daya listrik pada 120VAC <= 15A. Sebaliknya, perangkat ini tidak memerlukan pengetahuan misterius tentang bagaimana rumah Anda terhubung, selain itu ia memiliki satu atau lebih cabang dengan tiga cabang yang berlokasi yang menyediakan 120VAC <= 15A.

Antarmuka melakukan fungsi yang sangat mirip dalam kode. Objek dapat menyatakan bahwa variabel tertentu, parameter atau tipe pengembalian adalah tipe antarmuka. Antarmuka tidak dapat dipakai secara langsung dengan newkata kunci, tetapi objek saya dapat diberikan, atau menemukan, implementasi antarmuka yang perlu dikerjakan. Setelah objek memiliki dependensinya, ia tidak harus tahu persis apa itu dependensi, ia hanya harus tahu ia dapat memanggil metode X, Y dan Z pada dependensi. Implementasi antarmuka tidak harus tahu bagaimana mereka akan digunakan, mereka hanya harus tahu mereka akan diharapkan untuk memberikan metode X, Y dan Z dengan tanda tangan tertentu.

Dengan demikian, dengan mengabstraksikan banyak objek di belakang antarmuka yang sama, Anda memberikan serangkaian fungsionalitas umum kepada konsumen objek dari antarmuka itu. Anda tidak perlu tahu objeknya, misalnya, Daftar, Kamus, LinkedList, Daftar Pesanan, atau apa pun. Karena Anda tahu semua ini adalah jumlah IEn, Anda dapat menggunakan metode jumlah IEn untuk pergi melalui setiap elemen dalam koleksi ini satu per satu. Anda tidak perlu tahu bahwa kelas keluaran adalah ConsoleWriter, FileWriter, NetworkStreamWriter, atau bahkan MulticastWriter yang menggunakan jenis penulis lain; yang harus Anda ketahui adalah bahwa mereka semua adalah IWriters (atau apa pun), dan dengan demikian mereka memiliki metode "Tulis" yang dapat Anda masukkan string, dan string itu akan menjadi output.

KeithS
sumber
7

Meskipun jelas merupakan memperlakukan bagi programmer (pada awalnya, setidaknya) untuk memiliki banyak warisan, ini adalah kelalaian yang hampir sepele, dan Anda harus (dalam banyak kasus) tidak bergantung pada banyak warisan. Alasannya kompleks, tetapi jika Anda benar - benar ingin mempelajarinya, pertimbangkan pengalaman dari dua bahasa pemrograman yang paling terkenal (berdasarkan indeks TIOBE ) yang mendukungnya: C ++ dan Python (ke-3 dan ke-8 dengan terhormat).

Dalam Python, multiple inheritance didukung, namun hampir secara universal disalahpahami oleh programmer dan menyatakan bahwa Anda tahu cara kerjanya, berarti membaca dan memahami makalah ini pada topik: Method Resolution Order . Sesuatu yang lain, yang terjadi pada Python, adalah antarmuka semacam itu yang masuk ke bahasa - Zope.Interfaces.

Untuk C ++, google "hierarki berlian C ++" dan lihatlah keburukan yang akan menutupi Anda. C ++ pro tahu bagaimana menggunakan multiple inheritance. Orang lain biasanya hanya bermain-main tanpa mengetahui apa hasilnya. Hal lain yang menunjukkan betapa bermanfaatnya antarmuka adalah fakta, bahwa dalam banyak kasus suatu kelas mungkin perlu menimpa sepenuhnya perilaku orang tuanya. Dalam kasus seperti itu, implementasi orangtua tidak perlu dan hanya membebani kelas anak dengan memori untuk variabel pribadi orangtua, yang mungkin tidak masalah dalam usia C #, tetapi penting ketika Anda melakukan pemrograman tertanam. Jika Anda menggunakan antarmuka, masalah itu tidak ada.

Kesimpulannya, antarmuka, menurut pendapat saya, adalah bagian penting dari OOP, karena mereka menegakkan kontrak. Warisan berganda berguna dalam kasus terbatas, dan biasanya hanya untuk orang yang tahu cara menggunakannya. Jadi, jika Anda seorang pemula, Anda adalah orang yang diperlakukan oleh kurangnya pewarisan berganda - ini memberi Anda kesempatan yang lebih baik untuk tidak membuat kesalahan .

Juga, secara historis, ide untuk antarmuka telah berakar jauh lebih awal dari spesifikasi desain C # Microsoft. Kebanyakan orang menganggap C # sebagai pemutakhiran melalui Java (dalam banyak hal), dan tebak dari mana C # mendapatkan antarmuka dari - Java. Protokol adalah kata yang lebih tua untuk konsep yang sama, dan jauh lebih tua dari .NET.

Pembaruan: Sekarang saya melihat bahwa saya mungkin telah menjawab pertanyaan yang berbeda - mengapa antarmuka bukan pewarisan berganda, tetapi ini sepertinya jawaban yang Anda cari. Selain itu, bahasa OO harus memiliki setidaknya satu dari dua, dan jawaban lainnya telah mencakup pertanyaan awal Anda.

George Penn.
sumber
6

Sulit bagi saya untuk membayangkan kode C # yang bersih dan berorientasi objek tanpa menggunakan antarmuka. Anda menggunakannya kapan pun Anda ingin menegakkan ketersediaan fungsi tertentu tanpa memaksa kelas untuk mewarisi dari kelas dasar tertentu, dan ini memungkinkan kode Anda untuk memiliki tingkat penggandaan (rendah) yang relevan.

Saya tidak setuju bahwa pewarisan berganda lebih baik daripada memiliki antarmuka, bahkan sebelum kita berdebat bahwa pewarisan berganda datang dengan rasa sakitnya sendiri. Antarmuka adalah alat dasar untuk mengaktifkan polimorfisme dan penggunaan kembali kode, apa lagi yang dibutuhkan seseorang?

Daniel B
sumber
5

Saya pribadi suka kelas abstrak dan menggunakannya lebih dari sekedar antarmuka. Perbedaan utama datang dengan mengintegrasikan dengan .NET interface seperti IDisposable, IEnumerable dan sebagainya ... dan dengan COM interop. Juga, antarmuka sedikit lebih mudah untuk menulis daripada kelas abstrak, dan kelas dapat mengimplementasikan lebih dari satu antarmuka sementara itu hanya dapat mewarisi dari satu kelas.

Yang mengatakan, saya menemukan bahwa sebagian besar hal yang saya akan gunakan untuk antarmuka lebih baik dilayani oleh kelas abstrak. Fungsi virtual murni - fungsi abstrak - memungkinkan Anda untuk memaksa implementer untuk mendefinisikan fungsi yang mirip dengan cara antarmuka memaksa implementer untuk mendefinisikan semua anggotanya.

Namun, Anda biasanya menggunakan antarmuka saat Anda tidak ingin memaksakan desain tertentu pada kelas super, sementara Anda akan menggunakan kelas abstrak untuk memiliki desain yang dapat digunakan kembali yang sudah sebagian besar diimplementasikan.

Saya telah menggunakan antarmuka secara luas dengan menulis lingkungan plugin menggunakan namespace System.ComponentModel. Mereka sangat berguna.

Jonathan Henson
sumber
1
Sangat bagus! Saya kira Anda akan menyukai artikel saya di kelas abstrak. Abstraksi adalah segalanya .
Steven Jeuris
5

Saya bisa mengatakan saya berhubungan dengan itu. Ketika saya pertama kali mulai belajar tentang OO dan C #, saya juga tidak mendapatkan Antarmuka. Tidak apa-apa. Kami hanya perlu menemukan sesuatu yang akan membuat Anda menghargai kenyamanan antarmuka.

Biarkan saya mencoba dua pendekatan. Dan maafkan saya untuk generalisasi.

Coba 1

Katakanlah Anda penutur asli bahasa Inggris. Anda pergi ke negara lain di mana bahasa Inggris bukan bahasa ibu. Kamu butuh bantuan. Anda membutuhkan seseorang yang dapat membantu Anda.

Apakah Anda bertanya: "Hei, apakah Anda lahir di Amerika Serikat?" Ini warisan.

Atau apakah Anda bertanya: "Hei, apakah Anda berbicara bahasa Inggris"? Ini adalah antarmuka.

Jika Anda peduli tentang apa yang dilakukannya, Anda bisa mengandalkan antarmuka. Jika Anda peduli tentang apa itu, Anda mengandalkan warisan.

Tidak apa-apa mengandalkan warisan. Jika Anda membutuhkan seseorang yang berbicara bahasa Inggris, suka teh dan suka sepak bola, Anda lebih baik dilayani meminta orang Inggris. :)

Coba 2

Oke, mari kita coba contoh lain.

Anda menggunakan database yang berbeda dan Anda perlu menerapkan kelas abstrak untuk bekerja dengannya. Anda akan meneruskan kelas Anda ke beberapa kelas dari vendor DB.

public abstract class SuperDatabaseHelper
{
   void Connect (string User, string Password)
}

public abstract class HiperDatabaseHelper
{
   void Connect (string Password, string User)
}

Warisan berganda, katamu? Coba saja dengan case di atas. Kamu tidak bisa Kompiler tidak akan tahu metode Connect mana yang Anda coba panggil.

interface ISuperDatabaseHelper
{
  void Connect (string User, string Password)
}

interface IHiperDatabaseHelper
{
   void Connect (string Password, string User)
}

Sekarang, ada sesuatu yang dapat kita kerjakan - setidaknya dalam C # - di mana kita dapat mengimplementasikan antarmuka secara eksplisit.

public class MyDatabaseHelper : ISuperDatabaseHelper, IHiperDatabaseHelper
{
   IHiperDataBaseHelper.Connect(string Password, string User)
   {
      //
   }

   ISuperDataBaseHelper.Connect(string User, string Password)
   {
      //
   }

}

Kesimpulan

Contoh-contohnya bukan yang terbaik, tapi saya pikir itu intinya.

Anda hanya akan "mendapatkan" antarmuka saat Anda merasa membutuhkannya. Sampai mereka akan berpikir itu bukan untukmu.

Luiz Angelo
sumber
Try pertama adalah yang memberikan suara saya.
osundblad
1
Saya benar-benar menggunakan analogi Pembicara Bahasa Amerika vs. Bahasa Inggris mulai sekarang. Itu fantastis.
Bryan Boettcher
Dijelaskan dengan cara yang lebih sederhana! Fantastis.
Aimal Khan
4

Ada 2 alasan utama:

  1. Kurangnya pewarisan berganda. Anda dapat mewarisi dari satu kelas dasar dan mengimplementasikan sejumlah antarmuka. Itulah satu-satunya cara untuk "melakukan" multiple inheritance di .NET.
  2. Interoperabilitas COM. Apa pun yang perlu digunakan oleh teknologi "lama" harus memiliki antarmuka yang ditentukan.
Tangurena
sumber
Poin 1 jelas merupakan alasan dan alasan yang dikembangkan oleh pengembang microsoft sendiri
Pankaj Upadhyay
1
@Pankja Sebenarnya, mereka mengambil ide antarmuka dari Java (seperti bagian yang bagus dari fitur C #).
Oliver Weiler
3

Penggunaan antarmuka membantu sistem tetap dipisahkan dan dengan demikian lebih mudah untuk memperbaiki, mengubah, dan memindahkan. Ini adalah konsep yang sangat inti untuk ortodoksi berorientasi objek dan saya pertama kali belajar tentang hal itu ketika guru C ++ membuat "kelas abstrak murni" yang cukup setara dengan antarmuka.

Jesse C. Slicer
sumber
Decoupling penting karena menjaga komponen yang berbeda dari suatu sistem independen satu sama lain. Bahkan perubahan berdampak besar dalam satu komponen tidak beriak ke komponen lain. Pikirkan colokan listrik sebagai antarmuka ke perusahaan utilitas Anda (menentukan voltase dan pin fisik dan format steker). Berkat antarmuka ini, utilitas ini dapat sepenuhnya mengubah cara mereka menghasilkan daya (misalnya menggunakan teknologi surya), namun tidak satu pun perangkat yang akan melihat apalagi berubah.
miraculixx
3

Antarmuka sendiri tidak terlalu berguna. Tetapi ketika diimplementasikan oleh kelas konkret Anda melihat bahwa itu memberi Anda fleksibilitas untuk memiliki satu atau lebih implementasi. Bonusnya adalah bahwa objek yang menggunakan antarmuka tidak perlu tahu bagaimana detail implementasi sebenarnya berjalan - itu disebut enkapsulasi.

Ronald
sumber
2

Mereka sebagian besar digunakan untuk dapat digunakan kembali kode. Jika Anda kode ke antarmuka Anda dapat menggunakan kelas berbeda yang mewarisi dari antarmuka itu dan tidak merusak semuanya.

Juga mereka sangat berguna dalam layanan web di mana Anda ingin membiarkan klien tahu apa yang kelas lakukan (sehingga mereka dapat mengkonsumsinya) tetapi tidak ingin memberi mereka kode yang sebenarnya.

Tom Squires
sumber
2

Sebagai programmer / pengembang muda, hanya belajar C # Anda mungkin tidak melihat kegunaan antarmuka, karena Anda dapat menulis kode menggunakan kelas Anda dan kode berfungsi dengan baik, tetapi dalam skenario kehidupan nyata, membangun aplikasi yang skalabel, kuat, dan dapat dirawat melibatkan penggunaan beberapa arsitektur dan pola, yang hanya dapat dimungkinkan dengan menggunakan antarmuka, contohnya adalah injeksi ketergantungan.

Adewole Ayobami
sumber
1

Implementasi dunia nyata:

Anda bisa melemparkan objek sebagai tipe Antarmuka:

IHelper h = (IHelper)o;
h.HelperMethod();

Anda dapat membuat daftar antarmuka

List<IHelper> HelperList = new List<IHelper>();

Dengan objek-objek ini Anda dapat mengakses metode atau properti antarmuka mana saja. Dengan cara ini Anda dapat menentukan antarmuka untuk bagian Anda dari suatu program. Dan bangun logika di sekitarnya. Kemudian orang lain dapat mengimplementasikan antarmuka Anda di objek Bisnis mereka. Jika perubahan BO, mereka dapat mengubah logika untuk komponen antarmuka dan tidak memerlukan perubahan logika untuk bagian Anda.

SoylentGray
sumber
0

Antarmuka meminjamkan modularitas gaya plugin dengan menyediakan mekanisme bagi kelas untuk memahami (dan berlangganan) beberapa jenis pesan yang disampaikan sistem Anda. Saya akan menguraikan.

Dalam aplikasi Anda, Anda memutuskan bahwa setiap kali suatu formulir dimuat atau dimuat ulang Anda ingin semua hal yang dihostingnya dihapus. Anda mendefinisikan IClearantarmuka yang mengimplementasikan Clear. Selain itu, Anda memutuskan bahwa setiap kali pengguna menekan tombol simpan yang harus berusaha mempertahankan statusnya. Dengan demikian, semua yang patuh ISavemenerima pesan untuk mempertahankan kondisinya. Tentu saja, secara praktis, sebagian besar antarmuka menangani beberapa pesan.

Apa yang membuat antarmuka berbeda adalah bahwa perilaku umum dapat dicapai tanpa warisan. Kelas yang mengimplementasikan antarmuka yang diberikan hanya memahami bagaimana berperilaku ketika mengeluarkan perintah (pesan perintah) atau bagaimana merespons ketika ditanya (pesan permintaan). Pada dasarnya, kelas-kelas dalam aplikasi Anda memahami pesan yang disediakan aplikasi Anda. Ini membuatnya lebih mudah untuk membangun sistem modular di mana hal-hal dapat dicolokkan.

Dalam sebagian besar bahasa ada mekanisme (seperti LINQ ) untuk menanyakan hal-hal yang mematuhi antarmuka. Ini biasanya akan membantu Anda menghilangkan logika kondisional karena Anda tidak perlu mengatakan hal-hal yang berbeda (yang tidak perlu diturunkan dari rantai pewarisan yang sama) bagaimana berperilaku sama (sesuai dengan pesan tertentu). Alih-alih, Anda mengumpulkan semua yang memahami pesan tertentu (mematuhi antarmuka) dan menerbitkan pesan itu.

Misalnya, Anda dapat mengganti ...

Me.PublishDate.Clear()
Me.Subject.Clear()
Me.Body.Clear()

...dengan:

For Each ctl As IClear In Me.Controls.OfType(Of IClear)()
    ctl.Clear()
Next

Yang terdengar sangat efektif:

Dengarkan kamu, Dengarkan kamu! Apakah semua orang yang mengerti soal kliring, tolong Clearsekarang!

Dengan cara ini, kita secara terprogram dapat menghindari mengatakan setiap hal untuk membersihkan dirinya sendiri. Dan ketika item yang dapat dihapus ditambahkan di masa depan mereka hanya merespons tanpa kode tambahan.

Mario T. Lanza
sumber
0

Berikut ini adalah kodesemu:

class MyClass{

    private MyInterface = new MyInterfaceImplementationB();

    // Code using Thingy 

}

interface MyInterface{

    myMethod();

}

class MyInterfaceImplementationA{ myMethod(){ // method implementation A } }

class MyInterfaceImplementationB{ myMethod(){ // method implementation B } }

class MyInterfaceImplementationC{ myMethod(){ // method implementation C } }

Kelas-kelas terakhir dapat implementasi yang sama sekali berbeda.

Kecuali jika multiple inheritance dimungkinkan, inheritance memberlakukan implementasi kelas induk membuat semuanya menjadi lebih kaku. Pemrograman terhadap antarmuka di sisi lain dapat memungkinkan kode atau kerangka kerja Anda menjadi sangat fleksibel. Jika Anda pernah menemukan sebuah kasus di mana Anda berharap dapat bertukar kelas dalam rantai pewarisan, Anda akan mengerti alasannya.

Sebagai contoh, suatu kerangka kerja yang menyediakan Pembaca yang awalnya dimaksudkan untuk membaca data dari disk dapat diimplementasikan kembali untuk melakukan sesuatu yang sifatnya sama tetapi dengan cara yang sama sekali berbeda. Seperti menafsirkan kode Morse misalnya.

James Poulson
sumber