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?
sumber
Jawaban:
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.
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.
sumber
Assume
panggilan, 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.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.
sumber
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.
sumber
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.
sumber
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.
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.
sumber
Anda mungkin telah menggunakan
foreach
dan menemukannya sebagai alat iterasi yang cukup berguna. Tahukah Anda bahwa itu membutuhkan antarmuka untuk berfungsi, IEnumerable ?Itu tentu kasus konkret berbicara tentang kegunaan antarmuka.
sumber
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
new
kata 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.
sumber
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.
sumber
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?
sumber
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.
sumber
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.
Warisan berganda, katamu? Coba saja dengan case di atas. Kamu tidak bisa Kompiler tidak akan tahu metode Connect mana yang Anda coba panggil.
Sekarang, ada sesuatu yang dapat kita kerjakan - setidaknya dalam C # - di mana kita dapat mengimplementasikan antarmuka secara eksplisit.
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.
sumber
Ada 2 alasan utama:
sumber
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.
sumber
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.
sumber
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.
sumber
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.
sumber
Implementasi dunia nyata:
Anda bisa melemparkan objek sebagai tipe Antarmuka:
Anda dapat membuat daftar antarmuka
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.
sumber
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
IClear
antarmuka yang mengimplementasikanClear
. Selain itu, Anda memutuskan bahwa setiap kali pengguna menekan tombol simpan yang harus berusaha mempertahankan statusnya. Dengan demikian, semua yang patuhISave
menerima 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 ...
...dengan:
Yang terdengar sangat efektif:
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.
sumber
Berikut ini adalah kodesemu:
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.
sumber