Alasan untuk antarmuka benar-benar menghindari saya. Dari apa yang saya mengerti, ini adalah semacam pekerjaan untuk multi-inheritance tidak ada yang tidak ada di C # (atau jadi saya diberitahu).
Yang saya lihat adalah, Anda menetapkan beberapa anggota dan fungsi, yang kemudian harus didefinisikan ulang di kelas lagi. Sehingga membuat antarmuka menjadi mubazir. Rasanya seperti sintaksis ... yah, sampah bagi saya (Tolong jangan tersinggung berarti. Sampah seperti dalam hal-hal yang tidak berguna).
Dalam contoh yang diberikan di bawah ini diambil dari thread antarmuka C # berbeda pada stack overflow, saya hanya akan membuat kelas dasar yang disebut Pizza bukan antarmuka.
contoh mudah (diambil dari kontribusi stack overflow yang berbeda)
public interface IPizza
{
public void Order();
}
public class PepperoniPizza : IPizza
{
public void Order()
{
//Order Pepperoni pizza
}
}
public class HawaiiPizza : IPizza
{
public void Order()
{
//Order HawaiiPizza
}
}
struct
tipe.Jawaban:
Intinya adalah bahwa antarmuka merupakan kontrak . Seperangkat metode publik yang harus dimiliki oleh setiap kelas pelaksana. Secara teknis, antarmuka hanya mengatur sintaksis, yaitu metode apa yang ada, argumen apa yang mereka dapatkan dan apa yang mereka kembalikan. Biasanya mereka merangkum semantik juga, meskipun itu hanya dengan dokumentasi.
Anda kemudian dapat memiliki implementasi antarmuka yang berbeda dan menukarnya sesuka hati. Dalam contoh Anda, karena setiap instance pizza adalah
IPizza
Anda dapat menggunakan diIPizza
mana pun Anda menangani instance dari jenis pizza yang tidak dikenal. Contoh apa pun yang jenisnya diwarisi dariIPizza
dijamin dapat dipesan, karena memilikiOrder()
metode.Python tidak diketik secara statis, oleh karena itu tipe disimpan dan melihat saat runtime. Jadi, Anda dapat mencoba memanggil
Order()
metode pada objek apa pun. Runtime senang selama objek memiliki metode seperti itu dan mungkin hanya mengangkat bahu dan berkata "Meh." Jika tidak. Tidak demikian halnya dalam C #. Compiler bertanggung jawab untuk membuat panggilan yang benar dan jika hanya memiliki beberapa acakobject
kompiler belum tahu apakah instance selama runtime akan memiliki metode itu. Dari sudut pandang kompiler itu tidak valid karena tidak dapat memverifikasinya. (Anda dapat melakukan hal-hal seperti itu dengan refleksi ataudynamic
kata kunci, tapi itu agak jauh sekarang, saya kira.)Perhatikan juga bahwa antarmuka dalam arti biasa tidak harus berupa C #
interface
, bisa juga kelas abstrak atau bahkan kelas normal (yang bisa berguna jika semua subclass perlu berbagi beberapa kode umum - dalam kebanyakan kasus Namun,interface
cukuplah).sumber
foo
implementasinyaIWidget
, maka seorang programmer yang melihat panggilan untukfoo.woozle()
dapat melihat dokumentasiIWidget
dan mengetahui apa yang seharusnya dilakukan metode itu . Pemrogram mungkin tidak memiliki cara untuk mengetahui dari mana kode untuk implementasi aktual akan berasal, tetapi jenis apa pun yang mematuhiIWidget
kontrak antarmuka akan menerapkanfoo
dengan cara yang konsisten dengan kontrak itu. Sebaliknya, dalam bahasa yang dinamis, tidak akan ada titik rujukan yang jelas untuk apa yangfoo.woozle()
seharusnya.Tidak ada yang benar-benar menjelaskan secara sederhana bagaimana antarmuka berguna, jadi saya akan mencobanya (dan mencuri sedikit ide dari jawaban Shamim).
Mari kita mengambil ide layanan pemesanan pizza. Anda dapat memiliki beberapa jenis pizza dan tindakan umum untuk setiap pizza adalah menyiapkan pesanan dalam sistem. Setiap pizza harus disiapkan tetapi masing-masing pizza disiapkan secara berbeda . Misalnya, ketika pizza kerak isian dipesan sistem mungkin harus memverifikasi bahan-bahan tertentu yang tersedia di restoran dan menyisihkannya yang tidak diperlukan untuk pizza hidangan dalam.
Saat menulis ini dalam kode, secara teknis Anda bisa melakukannya
Namun, pizza parabola (dalam istilah C #) mungkin memerlukan properti yang berbeda untuk ditetapkan dalam
Prepare()
metode dari kerak yang diisi, dan dengan demikian Anda berakhir dengan banyak properti opsional, dan kelas tidak skala dengan baik (bagaimana jika Anda menambahkan baru jenis pizza).Cara yang tepat untuk menyelesaikan ini adalah dengan menggunakan antarmuka. Antarmuka menyatakan bahwa semua Pizza dapat disiapkan, tetapi setiap pizza dapat disiapkan secara berbeda. Jadi, jika Anda memiliki antarmuka berikut:
Sekarang kode penanganan pesanan Anda tidak perlu tahu persis jenis pizza apa yang dipesan untuk menangani bahan. Itu hanya memiliki:
Meskipun setiap jenis pizza disiapkan secara berbeda, bagian kode ini tidak harus peduli dengan jenis pizza yang kita hadapi, ia hanya tahu bahwa itu dipanggil untuk pizza dan oleh karena itu setiap panggilan untuk
Prepare
akan secara otomatis menyiapkan setiap pizza dengan benar berdasarkan jenisnya, meskipun koleksinya memiliki banyak jenis pizza.sumber
public
. Jadi di dalam antarmuka seharusnyavoid Prepare();
Bagi saya, ketika memulai, intinya hanya menjadi jelas ketika Anda berhenti memandanginya sebagai hal yang membuat kode Anda lebih mudah / lebih cepat untuk ditulis - ini bukan tujuan mereka. Mereka memiliki sejumlah kegunaan:
(Ini akan kehilangan analogi pizza, karena tidak mudah memvisualisasikan penggunaan ini)
Katakanlah Anda membuat game sederhana di layar dan ia akan memiliki makhluk yang berinteraksi dengan Anda.
A: Mereka dapat membuat kode Anda lebih mudah dipelihara di masa depan dengan memperkenalkan kopling longgar antara ujung depan dan implementasi ujung belakang Anda.
Anda dapat menulis ini sebagai permulaan, karena hanya akan ada troll:
Paling depan:
Dua minggu kemudian, pemasaran memutuskan Anda juga membutuhkan Orc, ketika mereka membaca tentang mereka di twitter, jadi Anda harus melakukan sesuatu seperti:
Paling depan:
Dan Anda dapat melihat bagaimana ini mulai menjadi berantakan. Anda dapat menggunakan antarmuka di sini sehingga ujung depan Anda akan ditulis satu kali dan (inilah bagian penting) yang diuji, dan Anda kemudian dapat menyambungkan item ujung belakang lebih lanjut sesuai kebutuhan:
Ujung depan adalah:
Ujung depan sekarang hanya peduli dengan antarmuka ICreature - tidak peduli tentang implementasi internal troll atau orc, tetapi hanya pada kenyataan bahwa mereka menerapkan ICreature.
Poin penting yang perlu diperhatikan ketika melihat ini dari sudut pandang ini adalah Anda juga bisa dengan mudah menggunakan kelas makhluk abstrak, dan dari perspektif ini, ini memiliki efek yang sama .
Dan Anda dapat mengekstrak ciptaan ke pabrik:
Dan ujung depan kita kemudian akan menjadi:
Ujung depan sekarang bahkan tidak harus memiliki referensi ke perpustakaan tempat Troll dan Orc diimplementasikan (asalkan pabrik berada di perpustakaan terpisah) - tidak perlu tahu apa-apa tentang mereka sama sekali.
B: Katakanlah Anda memiliki fungsionalitas yang hanya dimiliki oleh beberapa makhluk dalam struktur data Anda yang homogen , misalnya
Ujung depan bisa jadi:
C: Penggunaan untuk injeksi ketergantungan
Sebagian besar kerangka kerja ketergantungan injeksi lebih mudah untuk dikerjakan ketika ada hubungan yang sangat longgar antara kode ujung depan dan implementasi ujung belakang. Jika kami mengambil contoh pabrik kami di atas dan meminta pabrik kami mengimplementasikan antarmuka:
Ujung depan kami kemudian dapat menyuntikkan ini (misalnya, pengontrol API MVC) melalui konstruktor (biasanya):
Dengan kerangka kerja DI kami (mis. Ninject atau Autofac), kami dapat mengaturnya sehingga pada saat runtime instance CreatureFactory akan dibuat setiap kali ICreatureFactory diperlukan dalam sebuah konstruktor - ini membuat kode kami bagus dan sederhana.
Ini juga berarti bahwa ketika kita menulis unit test untuk controller kita, kita dapat memberikan ICreatureFactory yang diejek (mis. Jika implementasi konkret membutuhkan akses DB, kita tidak ingin unit test kita bergantung pada hal itu) dan dengan mudah menguji kode pada controller kita. .
D: Ada kegunaan lain misalnya Anda memiliki dua proyek A dan B yang karena alasan 'warisan' tidak terstruktur dengan baik, dan A memiliki referensi ke B.
Anda kemudian menemukan fungsionalitas dalam B yang perlu memanggil metode yang sudah dalam A. Anda tidak dapat melakukannya menggunakan implementasi konkret saat Anda mendapatkan referensi melingkar.
Anda dapat memiliki antarmuka yang dinyatakan dalam B yang diterapkan oleh kelas di A. Metode Anda dalam B dapat diberikan instance kelas yang mengimplementasikan antarmuka tanpa masalah, meskipun objek konkret adalah tipe dalam A.
sumber
Berikut adalah contoh Anda yang dijelaskan kembali:
sumber
Contoh di atas tidak masuk akal. Anda bisa menyelesaikan semua contoh di atas menggunakan kelas (kelas abstrak jika Anda ingin berperilaku hanya sebagai kontrak ):
Anda mendapatkan perilaku yang sama dengan antarmuka. Anda dapat membuat
List<Food>
dan mengulangi bahwa tanpa mengetahui kelas apa yang duduk di atas.Contoh yang lebih memadai adalah multiple inheritance:
Kemudian Anda bisa menggunakan semuanya sebagai
MenuItem
dan tidak peduli bagaimana mereka menangani setiap pemanggilan metode.sumber
Penjelasan sederhana dengan analogi
Masalah untuk Dipecahkan: Apa tujuan dari polimorfisme?
Analogi: Jadi saya orang asing di lokasi konstruksi.
Pedagang berjalan di lokasi konstruksi sepanjang waktu. Saya tidak tahu siapa yang akan berjalan melewati pintu-pintu itu. Tetapi pada dasarnya saya memberi tahu mereka apa yang harus dilakukan.
Masalah dengan pendekatan di atas adalah bahwa saya harus: (i) tahu siapa yang berjalan di pintu itu, dan tergantung pada siapa itu, saya harus memberi tahu mereka apa yang harus dilakukan. Itu berarti saya harus tahu segalanya tentang perdagangan tertentu. Ada biaya / manfaat yang terkait dengan pendekatan ini:
Implikasi mengetahui apa yang harus dilakukan:
Ini berarti jika kode tukang kayu berubah dari:
BuildScaffolding()
keBuildScaffold()
(yaitu sedikit perubahan nama) maka saya juga harus mengubah kelas panggilan (yaituForeperson
kelas) juga - Anda harus membuat dua perubahan pada kode alih-alih (pada dasarnya ) hanya satu. Dengan polimorfisme Anda (pada dasarnya) hanya perlu melakukan satu perubahan untuk mencapai hasil yang sama.Kedua, Anda tidak perlu selalu bertanya: siapa Anda? ok lakukan ini ... siapa kamu? ok lakukan itu ..... polimorfisme - itu KERING kode itu, dan sangat efektif dalam situasi tertentu:
dengan polimorfisme, Anda dapat dengan mudah menambahkan kelas pedagang tambahan tanpa mengubah kode apa pun yang ada. (Yaitu prinsip desain SOLID kedua: Prinsip buka-tutup).
Solusinya
Bayangkan sebuah skenario di mana, tidak peduli siapa yang berjalan di pintu, saya dapat mengatakan: "Bekerja ()" dan mereka melakukan pekerjaan hormat yang menjadi spesialisasi mereka: tukang ledeng akan berurusan dengan pipa, dan tukang listrik akan berurusan dengan kabel.
Manfaat dari pendekatan ini adalah: (i) Saya tidak perlu tahu persis siapa yang berjalan melalui pintu itu - yang perlu saya ketahui adalah bahwa mereka akan menjadi semacam tradie dan mereka dapat melakukan pekerjaan, dan kedua , (ii) saya tidak perlu tahu apa-apa tentang perdagangan tertentu itu. Tradie akan membereskannya.
Jadi alih-alih ini:
Saya dapat melakukan sesuatu seperti ini:
Apa untungnya?
Keuntungannya adalah jika persyaratan pekerjaan spesifik tukang kayu berubah dll, maka juru kunci tidak perlu mengubah kode-nya - dia tidak perlu tahu atau peduli. Yang penting adalah bahwa tukang kayu tahu apa yang dimaksud dengan Work (). Kedua, jika pekerja konstruksi jenis baru datang ke lokasi kerja, maka mandor tidak perlu tahu apa-apa tentang perdagangan - semua mandor peduli jika pekerja konstruksi (tukang las, tukang las, tukang kaca, dll.) Dapat menyelesaikan beberapa Pekerjaan ().
Ilustrasi Masalah dan Solusi (Dengan dan Tanpa Antarmuka):
Tanpa antarmuka (Contoh 1):
Tanpa antarmuka (Contoh 2):
Dengan antarmuka:
Ringkasan
Antarmuka memungkinkan Anda membuat orang melakukan pekerjaan yang ditugaskan kepadanya, tanpa Anda memiliki pengetahuan tentang siapa mereka sebenarnya atau apa yang bisa mereka lakukan secara spesifik. Hal ini memungkinkan Anda untuk dengan mudah menambahkan tipe baru (perdagangan) tanpa mengubah kode yang ada (baik secara teknis Anda memang mengubahnya sedikit), dan itulah manfaat nyata dari pendekatan OOP vs metodologi pemrograman yang lebih fungsional.
Jika Anda tidak memahami salah satu di atas atau jika tidak jelas tanyakan dalam komentar dan saya akan mencoba membuat jawabannya lebih baik.
sumber
Dengan tidak adanya bebek mengetik seperti yang Anda bisa gunakan dalam Python, C # bergantung pada antarmuka untuk memberikan abstraksi. Jika dependensi suatu kelas adalah tipe konkret, Anda tidak bisa meneruskan tipe apa pun - menggunakan antarmuka yang bisa Anda lewati dengan tipe apa pun yang mengimplementasikan antarmuka.
sumber
Contoh Pizza buruk karena Anda harus menggunakan kelas abstrak yang menangani pemesanan, dan pizza hanya mengganti jenis pizza, misalnya.
Anda menggunakan antarmuka ketika Anda memiliki properti bersama, tetapi kelas Anda mewarisi dari tempat yang berbeda, atau ketika Anda tidak memiliki kode umum yang bisa Anda gunakan. Sebagai contoh, ini adalah hal-hal yang dapat dibuang
IDisposable
, Anda tahu itu akan dibuang, Anda hanya tidak tahu apa yang akan terjadi ketika itu dibuang.Antarmuka hanyalah kontrak yang memberi tahu Anda beberapa hal yang dapat dilakukan objek, parameter apa dan jenis pengembalian apa yang diharapkan.
sumber
Pertimbangkan kasus di mana Anda tidak mengontrol atau memiliki kelas dasar.
Ambil kontrol visual misalnya, dalam .NET untuk Winforms mereka semua mewarisi dari Kontrol kelas dasar, yang sepenuhnya ditentukan dalam kerangka .NET.
Mari kita asumsikan Anda dalam bisnis membuat kontrol khusus. Anda ingin membuat tombol baru, kotak teks, tampilan daftar, kisi, yang lainnya dan Anda ingin semuanya memiliki fitur tertentu yang unik untuk rangkaian kontrol Anda.
Misalnya Anda mungkin ingin cara umum untuk menangani tema, atau cara umum untuk menangani pelokalan.
Dalam hal ini Anda tidak dapat "hanya membuat kelas dasar" karena jika Anda melakukannya, Anda harus menerapkan kembali semua yang berhubungan dengan kontrol.
Sebaliknya Anda akan turun dari Button, TextBox, ListView, GridView, dll. Dan menambahkan kode Anda.
Tapi ini menimbulkan masalah, bagaimana Anda sekarang dapat mengidentifikasi kontrol mana yang "milikmu", bagaimana Anda bisa membangun beberapa kode yang mengatakan "untuk semua kontrol pada formulir yang menjadi milikku, atur tema menjadi X".
Masukkan antarmuka.
Antarmuka adalah cara untuk melihat objek, untuk menentukan bahwa objek mematuhi kontrak tertentu.
Anda akan membuat "YourButton", turun dari Button, dan menambahkan dukungan untuk semua antarmuka yang Anda butuhkan.
Ini memungkinkan Anda untuk menulis kode seperti berikut:
Ini tidak akan mungkin tanpa antarmuka, alih-alih Anda harus menulis kode seperti ini:
sumber
Dalam hal ini, Anda bisa (dan mungkin akan) mendefinisikan kelas dasar Pizza dan mewarisinya. Namun, ada dua alasan di mana Antarmuka memungkinkan Anda melakukan hal-hal yang tidak dapat dicapai dengan cara lain:
Sebuah kelas dapat mengimplementasikan banyak antarmuka. Itu hanya mendefinisikan fitur yang harus dimiliki kelas. Menerapkan berbagai antarmuka berarti bahwa suatu kelas dapat memenuhi beberapa fungsi di tempat yang berbeda.
Antarmuka dapat didefinisikan dalam ruang lingkup yang lebih tinggi dari kelas atau pemanggil. Ini berarti Anda dapat memisahkan fungsionalitas, memisahkan ketergantungan proyek, dan menjaga fungsionalitas dalam satu proyek atau kelas, dan implementasi ini di tempat lain.
Salah satu implikasi dari 2 adalah bahwa Anda dapat mengubah kelas yang sedang digunakan, hanya membutuhkannya mengimplementasikan antarmuka yang sesuai.
sumber
Pertimbangkan Anda tidak dapat menggunakan banyak pewarisan dalam C #, dan kemudian lihat kembali pertanyaan Anda.
sumber
Antarmuka = kontrak, digunakan untuk kopling longgar (lihat GRASP ).
sumber
Jika saya bekerja pada API untuk menggambar bentuk, saya mungkin ingin menggunakan DirectX atau panggilan grafik, atau OpenGL. Jadi, saya akan membuat antarmuka, yang akan abstrak implementasi saya dari apa yang Anda panggil.
Jadi Anda memanggil metode pabrik:
MyInterface i = MyGraphics.getInstance()
. Kemudian, Anda memiliki kontrak, sehingga Anda tahu fungsi apa yang dapat Anda harapkanMyInterface
. Jadi, Anda dapat meneleponi.drawRectangle
ataui.drawCube
mengetahui bahwa jika Anda menukar satu pustaka dengan pustaka lain, bahwa fungsinya didukung.Ini menjadi lebih penting jika Anda menggunakan Dependency Injection, seperti yang Anda bisa, dalam file XML, menukar implementasi.
Jadi, Anda mungkin memiliki satu perpustakaan crypto yang dapat diekspor yang untuk penggunaan umum, dan yang lain hanya untuk dijual ke perusahaan-perusahaan Amerika, dan perbedaannya adalah Anda mengubah file konfigurasi, dan sisanya dari program ini tidak berubah.
Ini digunakan banyak dengan koleksi di. NET, karena Anda hanya harus menggunakan, misalnya,
List
variabel, dan jangan khawatir apakah itu ArrayList atau LinkedList.Selama Anda membuat kode untuk antarmuka maka pengembang dapat mengubah implementasi aktual dan sisa program tidak berubah.
Ini juga berguna ketika pengujian unit, karena Anda dapat mencemooh seluruh antarmuka, jadi, saya tidak harus pergi ke database, tetapi untuk implementasi mencemooh yang hanya mengembalikan data statis, jadi saya dapat menguji metode saya tanpa khawatir jika database sedang dalam pemeliharaan atau tidak.
sumber
Antarmuka benar-benar sebuah kontrak yang harus diikuti oleh kelas-kelas pelaksana, ini sebenarnya merupakan dasar untuk hampir semua pola desain yang saya tahu.
Dalam contoh Anda, antarmuka dibuat karena dengan demikian segala sesuatu yang IS A Pizza, yang berarti mengimplementasikan antarmuka Pizza, dijamin telah diterapkan
Setelah kode yang disebutkan, Anda dapat memiliki sesuatu seperti ini:
Dengan cara ini Anda menggunakan polimorfisme dan yang Anda pedulikan adalah objek Anda merespons pesanan ().
sumber
Saya melakukan pencarian untuk kata "komposisi" di halaman ini dan tidak melihatnya sekali. Jawaban ini sangat banyak selain jawaban yang disebutkan di atas.
Salah satu alasan yang sangat penting untuk menggunakan antarmuka dalam Proyek Berorientasi Objek adalah bahwa mereka memungkinkan Anda untuk memilih komposisi daripada warisan. Dengan mengimplementasikan antarmuka, Anda dapat memisahkan implementasi dari berbagai algoritma yang Anda terapkan padanya.
Tutorial "Pola Penghias" yang luar biasa ini oleh Derek Banas (yang - cukup lucu - juga menggunakan pizza sebagai contoh) adalah ilustrasi yang bermanfaat:
https://www.youtube.com/watch?v=j40kRwSm4VE
sumber
Antarmuka adalah untuk menerapkan koneksi antara kelas yang berbeda. misalnya, Anda memiliki kelas untuk mobil dan pohon;
Anda ingin menambahkan fungsionalitas yang dapat dibakar untuk kedua kelas. Tetapi setiap kelas memiliki cara mereka sendiri untuk membakar. jadi Anda hanya membuat;
sumber
Anda akan mendapatkan antarmuka, saat Anda membutuhkannya :) Anda dapat mempelajari contoh, tetapi Anda membutuhkan Aha! efek untuk benar-benar mendapatkannya.
Sekarang Anda tahu antarmuka apa, hanya kode tanpa mereka. Cepat atau lambat Anda akan mengalami masalah, di mana penggunaan antarmuka akan menjadi hal yang paling wajar untuk dilakukan.
sumber
Saya terkejut bahwa tidak banyak posting berisi satu alasan paling penting untuk sebuah antarmuka: Pola Desain . Ini adalah gambaran yang lebih besar dalam menggunakan kontrak, dan meskipun itu adalah sintaksis dekorasi untuk kode mesin (jujur, kompiler mungkin hanya mengabaikannya), abstraksi dan antarmuka sangat penting untuk OOP, pemahaman manusia, dan arsitektur sistem yang kompleks.
Mari kita memperluas analogi pizza untuk mengatakan hidangan lengkap 3 fledge. Kami masih akan memiliki
Prepare()
antarmuka inti untuk semua kategori makanan kami, tetapi kami juga akan memiliki deklarasi abstrak untuk pilihan hidangan (starter, main, dessert), dan properti yang berbeda untuk jenis makanan (gurih / manis, vegetarian / non-vegetarian, bebas gluten dll).Berdasarkan spesifikasi ini, kita dapat menerapkan pola Pabrik Abstrak untuk membuat konsep seluruh proses, tetapi menggunakan antarmuka untuk memastikan bahwa hanya fondasi yang konkret. Segala sesuatu yang lain bisa menjadi fleksibel atau mendorong polimorfisme, namun mempertahankan enkapsulasi antara berbagai kelas
Course
yang mengimplementasikanICourse
antarmuka.Jika saya punya lebih banyak waktu, saya ingin membuat contoh lengkap dari ini, atau seseorang dapat memperluas ini untuk saya, tetapi secara ringkas, antarmuka C # akan menjadi alat terbaik dalam merancang sistem jenis ini.
sumber
Berikut ini antarmuka untuk objek yang memiliki bentuk persegi panjang:
Yang dibutuhkan adalah Anda menerapkan cara untuk mengakses lebar dan tinggi objek.
Sekarang mari kita mendefinisikan metode yang akan bekerja pada objek apa pun yang
IRectangular
:Itu akan mengembalikan area objek persegi panjang.
Mari kita implementasikan kelas
SwimmingPool
yang persegi panjang:Dan kelas lain
House
yang juga persegi panjang:Karena itu, Anda dapat memanggil
Area
metode ini di rumah atau kolam renang:Dengan cara ini, kelas Anda dapat "mewarisi" perilaku (metode statis) dari sejumlah antarmuka.
sumber
Antarmuka mendefinisikan kontrak antara penyedia fungsionalitas tertentu dan konsumen yang terkait. Ini memisahkan implementasi dari kontrak (antarmuka). Anda harus melihat arsitektur dan desain berorientasi objek. Anda mungkin ingin memulai dengan wikipedia: http://en.wikipedia.org/wiki/Interface_(computing)
sumber
Apa ?
Antarmuka pada dasarnya adalah kontrak yang harus diikuti oleh semua kelas yang mengimplementasikan Antarmuka. Mereka terlihat seperti kelas tetapi tidak memiliki implementasi.
Dalam
C#
Nama antarmuka menurut konvensi ditentukan oleh Awalan 'I' jadi jika Anda ingin memiliki antarmuka yang disebut bentuk, Anda akan mendeklarasikannya sebagaiIShapes
Sekarang kenapa ?
Improves code re-usability
Katakanlah Anda ingin menggambar
Circle
,Triangle.
Anda dapat mengelompokkannya bersama dan memanggil merekaShapes
dan memiliki metode untuk menggambarCircle
danTriangle
Tetapi memiliki implementasi konkret akan menjadi ide yang buruk karena besok Anda mungkin memutuskan untuk memiliki 2 lagiShapes
Rectangle
&Square
. Sekarang ketika Anda menambahkannya, ada kemungkinan besar Anda dapat merusak bagian lain dari kode Anda.Dengan Antarmuka Anda mengisolasi implementasi yang berbeda dari Kontrak
Skenario Langsung Hari 1
Anda diminta membuat Aplikasi untuk Menggambar Lingkaran dan Segitiga
Skenario Langsung Hari 2
Jika Anda diminta menambahkan
Square
danRectangle
memasukkannya, yang harus Anda lakukan adalah membuat implentasinyaclass Square: IShapes
danMain
menambahkan ke daftarshapes.Add(new Square());
sumber
Ada banyak jawaban bagus di sini tetapi saya ingin mencoba dari sudut pandang yang sedikit berbeda.
Anda mungkin akrab dengan prinsip-prinsip SOLID desain berorientasi objek. Singkatnya:
S - Prinsip Tanggung Jawab Tunggal O - Prinsip Terbuka / Tertutup L - Prinsip Pengganti Liskov I - Prinsip Segregasi Antarmuka D - Prinsip Pembalikan Ketergantungan
Mengikuti prinsip-prinsip SOLID membantu menghasilkan kode yang bersih, berfaktor dengan baik, kohesif, dan secara longgar digabungkan. Mengingat bahwa:
maka apa pun yang membantu pengelolaan ketergantungan adalah kemenangan besar. Antarmuka dan Prinsip Ketergantungan Inversi benar-benar membantu memisahkan kode dari ketergantungan pada kelas-kelas yang konkret, sehingga kode dapat ditulis dan dipertimbangkan dalam hal perilaku daripada implementasi. Ini membantu memecah kode menjadi komponen-komponen yang dapat dikomposisikan pada saat runtime daripada waktu kompilasi dan juga berarti komponen-komponen itu dapat dengan mudah dicolokkan masuk dan keluar tanpa harus mengubah sisa kode.
Antarmuka membantu khususnya dengan Prinsip Ketergantungan Inversi, di mana kode dapat dipecah menjadi kumpulan layanan, dengan masing-masing layanan dijelaskan oleh antarmuka. Layanan kemudian dapat "disuntikkan" ke dalam kelas saat runtime dengan mengirimkannya sebagai parameter konstruktor. Teknik ini benar-benar menjadi penting jika Anda mulai menulis unit test dan menggunakan pengembangan yang digerakkan oleh tes. Cobalah! Anda akan dengan cepat memahami bagaimana antarmuka membantu memecah kode menjadi potongan-potongan yang dapat dikelola yang dapat diuji secara terpisah.
sumber
Tujuan utama antarmuka adalah membuat kontrak antara Anda dan kelas lain yang mengimplementasikan antarmuka yang membuat kode Anda dipisahkan dan memungkinkan pengembangan.
sumber
Ini adalah contoh yang sangat bagus.
Lain, dalam hal pernyataan beralih, Anda tidak lagi perlu mempertahankan dan beralih setiap kali Anda ingin melakukan tugas dengan cara tertentu.
Dalam contoh pizza Anda, jika ingin membuat pizza, antarmuka adalah semua yang Anda butuhkan, dari sana setiap pizza menangani sendiri logikanya.
Ini membantu mengurangi kopling dan kompleksitas siklomatik. Anda harus tetap menerapkan logika tetapi akan ada lebih sedikit Anda harus melacak dalam gambar yang lebih luas.
Untuk setiap pizza, Anda kemudian dapat melacak informasi khusus untuk pizza itu. Apa yang dimiliki pizza lain tidak masalah karena hanya pizza lain yang perlu diketahui.
sumber
Cara paling sederhana untuk berpikir tentang antarmuka adalah mengenali apa arti warisan. Jika kelas CC mewarisi kelas C, itu berarti keduanya:
Kedua fungsi warisan itu dalam beberapa hal bersifat independen; meskipun warisan berlaku keduanya secara bersamaan, juga dimungkinkan untuk menerapkan yang kedua tanpa yang pertama. Ini berguna karena mengizinkan objek untuk mewarisi anggota dari dua atau lebih kelas yang tidak terkait jauh lebih rumit daripada membiarkan satu jenis hal dapat disubstitusikan untuk beberapa jenis.
Antarmuka agak seperti kelas dasar abstrak, tetapi dengan perbedaan utama: objek yang mewarisi kelas dasar tidak dapat mewarisi kelas lain. Sebaliknya, suatu objek dapat mengimplementasikan antarmuka tanpa mempengaruhi kemampuannya untuk mewarisi kelas yang diinginkan atau mengimplementasikan antarmuka lain.
Salah satu fitur bagus dari ini (kurang dimanfaatkan dalam .net framework, IMHO) adalah bahwa mereka memungkinkan untuk menunjukkan secara deklaratif hal-hal yang dapat dilakukan objek. Beberapa objek, misalnya, akan menginginkan objek sumber data dari mana mereka dapat mengambil sesuatu dengan indeks (seperti yang mungkin dengan Daftar), tetapi mereka tidak perlu menyimpan apa pun di sana. Rutinitas lain akan membutuhkan objek penyimpanan data di mana mereka dapat menyimpan hal-hal tidak dengan indeks (seperti dengan Collection.Add), tetapi mereka tidak perlu membaca apa pun kembali. Beberapa tipe data akan memungkinkan akses menurut indeks, tetapi tidak akan mengizinkan penulisan; yang lain akan mengizinkan penulisan, tetapi tidak akan mengizinkan akses berdasarkan indeks. Beberapa, tentu saja, akan memungkinkan keduanya.
Jika ReadableByIndex dan Appendable adalah kelas dasar yang tidak terkait, tidak mungkin untuk menentukan tipe yang dapat diteruskan ke hal-hal yang mengharapkan ReadableByIndex dan hal-hal yang mengharapkan suatu Appendable. Seseorang dapat mencoba mengurangi ini dengan memiliki ReadableByIndex atau Appendable yang berasal dari yang lain; kelas turunan harus menyediakan anggota publik untuk kedua tujuan, tetapi memperingatkan bahwa beberapa anggota publik mungkin tidak benar-benar berfungsi. Beberapa kelas dan antarmuka Microsoft melakukan itu, tetapi itu agak menjijikkan. Pendekatan yang lebih bersih adalah memiliki antarmuka untuk tujuan yang berbeda, dan kemudian memiliki objek yang mengimplementasikan antarmuka untuk hal-hal yang sebenarnya dapat mereka lakukan. Jika seseorang memiliki antarmuka IReadableByIndex dan antarmuka lainnya IAppendable,
sumber
Antarmuka juga dapat dirantai daisy untuk membuat antarmuka lain. Kemampuan ini untuk mengimplementasikan beberapa Antarmuka memberi pengembang keuntungan dari menambahkan fungsionalitas ke kelas mereka tanpa harus mengubah fungsionalitas kelas saat ini (Prinsip SOLID)
O = "Kelas harus terbuka untuk ekstensi tetapi ditutup untuk modifikasi"
sumber
Bagi saya kelebihan / manfaat antarmuka adalah lebih fleksibel daripada kelas abstrak. Karena Anda hanya dapat mewarisi 1 kelas abstrak tetapi Anda dapat mengimplementasikan banyak antarmuka, perubahan pada sistem yang mewarisi kelas abstrak di banyak tempat menjadi bermasalah. Jika diwarisi di 100 tempat, perubahan memerlukan perubahan ke semua 100. Tapi, dengan antarmuka, Anda dapat menempatkan perubahan baru di antarmuka baru dan cukup gunakan antarmuka itu di tempat yang diperlukan (Antarmuka Seq. Dari SOLID). Selain itu, penggunaan memori tampaknya akan kurang dengan antarmuka sebagai objek dalam contoh antarmuka digunakan hanya sekali dalam memori meskipun berapa banyak tempat mengimplementasikan antarmuka.
sumber
Antarmuka digunakan untuk mendorong konsistensi, dengan cara yang digabungkan secara longgar yang membuatnya berbeda dengan kelas abstrak yang digabungkan dengan erat. Itulah sebabnya juga biasanya didefinisikan sebagai kontrak. Kelas mana pun yang mengimplementasikan antarmuka harus mematuhi "aturan / sintaksis" didefinisikan oleh antarmuka dan tidak ada elemen konkret di dalamnya.
Saya hanya akan memberikan contoh yang didukung oleh grafik di bawah ini.
Bayangkan di sebuah pabrik ada 3 jenis mesin. Mesin persegi panjang, mesin segitiga dan mesin poligon. Waktu kompetitif dan Anda ingin merampingkan pelatihan operator. Anda hanya ingin melatih mereka dalam satu metodologi memulai dan menghentikan mesin sehingga Anda memiliki tombol mulai hijau dan tombol berhenti merah. Jadi sekarang di 3 mesin yang berbeda Anda memiliki cara yang konsisten untuk memulai dan menghentikan 3 jenis mesin. Sekarang bayangkan mesin ini adalah kelas dan kelas perlu memiliki metode mulai dan berhenti, bagaimana Anda akan mendorong konsistensi di kelas-kelas ini yang bisa sangat berbeda? Antarmuka adalah jawabannya.
Contoh sederhana untuk membantu Anda memvisualisasikan, orang mungkin bertanya mengapa tidak menggunakan kelas abstrak? Dengan antarmuka, objek tidak harus terkait atau diwariskan secara langsung dan Anda masih dapat mendorong konsistensi di berbagai kelas.
sumber
Izinkan saya menggambarkan ini dengan perspektif yang berbeda. Mari kita buat cerita sesuai dengan contoh yang saya tunjukkan di atas;
Program, Mesin, dan Mesin adalah aktor dari kisah kami. Program ingin dijalankan tetapi tidak memiliki kemampuan dan Machine tahu cara menjalankannya. Machine dan IMachine adalah teman baik tetapi Program tidak berbicara dengan Machine. Jadi Program dan IMachine membuat kesepakatan dan memutuskan bahwa IMachine akan memberi tahu Program bagaimana menjalankan dengan melihat Mesin (seperti reflektor).
Dan Program mempelajari cara menjalankannya dengan bantuan IMachine.
Antarmuka menyediakan komunikasi dan mengembangkan proyek yang digabungkan secara longgar.
PS: Saya sudah menggunakan metode kelas beton sebagai privat. Tujuan saya di sini adalah untuk mencapai secara longgar digabungkan dengan mencegah mengakses properti dan metode kelas beton, dan hanya menyisakan cara untuk menjangkau mereka melalui antarmuka. (Jadi saya mendefinisikan metode antarmuka secara eksplisit).
sumber
Saya tahu saya sangat terlambat .. (hampir sembilan tahun), tetapi jika seseorang ingin penjelasan kecil maka Anda dapat melakukannya untuk ini:
Dengan kata-kata sederhana, Anda menggunakan Antarmuka ketika Anda tahu apa yang bisa dilakukan Obyek atau fungsi apa yang akan kami terapkan pada objek .. Contoh Masukkan, Perbarui, dan Hapus.
Catatan Penting: Antarmuka SELALU bersifat publik.
Semoga ini membantu.
sumber