Jadi katakanlah saya memiliki antarmuka ini:
public interface IBox
{
public void setSize(int size);
public int getSize();
public int getArea();
//...and so on
}
Dan saya memiliki kelas yang mengimplementasikannya:
public class Rectangle implements IBox
{
private int size;
//Methods here
}
Jika saya ingin menggunakan antarmuka IBox, saya tidak bisa membuat instance darinya, dengan cara:
public static void main(String args[])
{
Ibox myBox=new Ibox();
}
Baik? Jadi sebenarnya saya harus melakukan ini:
public static void main(String args[])
{
Rectangle myBox=new Rectangle();
}
Jika itu benar, maka satu-satunya tujuan antarmuka adalah untuk memastikan bahwa kelas yang mengimplementasikan antarmuka telah mendapatkan metode yang benar di dalamnya seperti yang dijelaskan oleh antarmuka? Atau apakah ada penggunaan antarmuka lainnya?
java
oop
language-features
interface
Klik Upvote
sumber
sumber
Jawaban:
Antarmuka adalah cara untuk membuat kode Anda lebih fleksibel. Apa yang Anda lakukan adalah ini:
Kemudian, nanti, jika Anda memutuskan ingin menggunakan jenis kotak yang berbeda (mungkin ada perpustakaan lain, dengan jenis kotak yang lebih baik), Anda beralih kode Anda ke:
Setelah terbiasa, Anda akan menemukan cara yang bagus (sebenarnya penting) untuk bekerja.
Alasan lain adalah, misalnya, jika Anda ingin membuat daftar kotak dan melakukan beberapa operasi pada masing-masing, tetapi Anda ingin daftar berisi berbagai jenis kotak. Pada setiap kotak yang dapat Anda lakukan:
(dengan asumsi IBox memiliki metode close ()) meskipun kelas sebenarnya dari myBox berubah tergantung pada kotak yang Anda gunakan dalam iterasi.
sumber
Apa yang membuat antarmuka tidak bermanfaat fakta bahwa "Anda dapat mengubah pikiran Anda dan menggunakan implementasi yang berbeda di lain waktu dan hanya perlu mengubah satu tempat di mana objek dibuat". Itu bukan masalah.
Poin sebenarnya sudah ada dalam namanya: mereka mendefinisikan antarmuka yang dapat diterapkan oleh siapa saja untuk menggunakan semua kode yang beroperasi pada antarmuka itu. Contoh terbaik adalah
java.util.Collections
yang menyediakan semua jenis metode berguna yang beroperasi secara eksklusif pada antarmuka, sepertisort()
ataureverse()
untukList
. Intinya di sini adalah bahwa kode ini sekarang dapat digunakan untuk mengurutkan atau membalikkan setiap kelas yang mengimplementasikanList
antarmuka - tidak hanyaArrayList
danLinkedList
, tetapi juga kelas yang Anda tulis sendiri, yang dapat diimplementasikan dengan cara yang orang-orang yang menulisjava.util.Collections
tidak pernah bayangkan.Dengan cara yang sama, Anda dapat menulis kode yang beroperasi pada antarmuka yang terkenal, atau antarmuka yang Anda tentukan, dan orang lain dapat menggunakan kode Anda tanpa harus meminta Anda untuk mendukung kelas mereka.
Penggunaan antarmuka lain yang umum adalah untuk Callback. Misalnya, java.swing.table.TableCellRenderer , yang memungkinkan Anda untuk memengaruhi bagaimana tabel Swing menampilkan data dalam kolom tertentu. Anda mengimplementasikan antarmuka itu, meneruskan contoh ke
JTable
, dan pada beberapa titik selama rendering tabel, kode Anda akan dipanggil untuk melakukan hal-hal tersebut.sumber
you can write code that operates on well-known interfaces, or interfaces you define
Salah satu dari banyak kegunaan yang saya baca adalah di mana yang sulit tanpa multi-inheritance-using-interface di Jawa:
Sekarang, Bayangkan sebuah kasus di mana:
tapi,
Desain yang lebih baik adalah:
Animal tidak memiliki metode chew () dan sebagai gantinya diletakkan di antarmuka sebagai:
dan minta kelas Reptil mengimplementasikan ini dan bukan Burung (karena Burung tidak bisa mengunyah):
dan memetikan burung hanya:
sumber
Reptile
"mengunyah", maka bukan itu sendiri adalah "kunyah". Konvensi (kadang-kadang) antarmuka penamaan Apapun yang seharusnya hanya diterapkan di mana masuk akal. Memberi nama antarmukaPredator
akan lebih sesuai di sini.Tujuan dari antarmuka adalah polimorfisme , alias subtitusi jenis . Misalnya, diberikan metode berikut:
Saat memanggil
scale
metode, Anda bisa memberikan nilai apa pun dari tipe yang mengimplementasikanIBox
antarmuka. Dengan kata lain, jikaRectangle
danSquare
keduanya diimplementasikanIBox
, Anda dapat memberikan aRectangle
atau aSquare
dimanapunIBox
diharapkan.sumber
Antarmuka memungkinkan bahasa yang diketik secara statis untuk mendukung polimorfisme. Purist Berorientasi Objek akan bersikeras bahwa bahasa harus menyediakan warisan, enkapsulasi, modularitas dan polimorfisme agar menjadi bahasa Berorientasi Objek dengan fitur lengkap. Dalam bahasa yang diketik secara dinamis - atau diketik bebek - (seperti Smalltalk,) polimorfisme adalah sepele; Namun, dalam bahasa yang diketik secara statis (seperti Java atau C #,) polimorfisme jauh dari sepele (pada kenyataannya, di permukaan tampaknya bertentangan dengan gagasan mengetik kuat.)
Biarkan saya menunjukkan:
Dalam bahasa yang diketik secara dinamis (atau diketik bebek) (seperti Smalltalk), semua variabel adalah referensi ke objek (tidak kurang dan tidak lebih.) Jadi, di Smalltalk, saya bisa melakukan ini:
Kode itu:
makeNoise
ke babi.Kode Java yang sama akan terlihat seperti ini (membuat asumsi bahwa Bebek dan Sapi adalah subkelas Hewan:
Itu semua baik dan bagus, sampai kami memperkenalkan kelas Sayuran. Sayuran memiliki beberapa perilaku yang sama dengan Hewan, tetapi tidak semua. Misalnya, Hewan dan Sayuran mungkin bisa tumbuh, tetapi jelas sayuran tidak membuat kebisingan dan hewan tidak bisa dipanen.
Di Smalltalk, kita bisa menulis ini:
Ini berfungsi dengan baik di Smalltalk karena itu diketik bebek (jika berjalan seperti bebek, dan dukun seperti bebek - itu adalah bebek.) Dalam hal ini, ketika pesan dikirim ke objek, pencarian dilakukan pada daftar metode penerima, dan jika metode yang cocok ditemukan, itu disebut. Jika tidak, beberapa jenis pengecualian NoSuchMethodError dilemparkan - tetapi semuanya dilakukan saat runtime.
Tetapi di Jawa, bahasa yang diketik secara statis, jenis apa yang bisa kita tetapkan untuk variabel kita? Jagung perlu diwariskan dari Sayuran, untuk mendukung tumbuh, tetapi tidak dapat mewarisi dari Hewan, karena tidak membuat kebisingan. Sapi perlu diwariskan dari Hewan untuk mendukung makeNoise, tetapi tidak dapat mewarisi dari Sayuran karena tidak boleh menerapkan panen. Sepertinya kita membutuhkan banyak warisan - kemampuan untuk mewarisi dari lebih dari satu kelas. Tapi itu ternyata menjadi fitur bahasa yang cukup sulit karena semua kasus tepi yang muncul (apa yang terjadi ketika lebih dari satu superclass paralel menerapkan metode yang sama ?, dll.)
Datanglah antarmuka ...
Jika kita membuat kelas Hewan dan Sayuran, dengan masing-masing menerapkan Growable, kita dapat mendeklarasikan bahwa Sapi kita adalah Hewan dan Jagung kita adalah Sayuran. Kami juga dapat menyatakan bahwa Hewan dan Sayuran adalah Growable. Itu memungkinkan kami menulis ini untuk menumbuhkan segalanya:
Dan ini memungkinkan kita melakukan ini, untuk membuat suara binatang:
Keuntungan dari bahasa yang diketik bebek adalah Anda mendapatkan polimorfisme yang benar-benar bagus: semua yang harus dilakukan kelas untuk memberikan perilaku adalah menyediakan metode. Selama semua orang bermain bagus, dan hanya mengirim pesan yang cocok dengan metode yang ditentukan, semuanya baik. Kelemahannya adalah jenis kesalahan di bawah ini tidak diketahui sampai runtime:
Bahasa yang diketik secara statis memberikan "pemrograman berdasarkan kontrak" yang jauh lebih baik, karena mereka akan menangkap dua jenis kesalahan di bawah ini pada waktu kompilasi:
-
Jadi .... untuk meringkas:
Implementasi antarmuka memungkinkan Anda menentukan jenis hal yang dapat dilakukan objek (interaksi) dan pewarisan Kelas memungkinkan Anda menentukan cara melakukan sesuatu (implementasi).
Antarmuka memberi kita banyak manfaat polimorfisme "benar", tanpa harus mengorbankan pemeriksaan tipe kompiler.
sumber
Biasanya Antarmuka menentukan antarmuka yang harus Anda gunakan (seperti namanya ;-)). Sampel
Sekarang fungsi Anda
foo
menerimaArrayList
s,LinkedList
s, ... tidak hanya satu jenis.Yang paling penting di Java adalah Anda bisa mengimplementasikan banyak antarmuka tetapi Anda hanya bisa memperluas satu kelas! Sampel:
mungkin tapi tidak!Di atas kode Anda juga bisa menjadi:
IBox myBox = new Rectangle();
. Yang penting sekarang, bahwa myBox ONLY berisi metode / bidang dari IBox dan bukan (mungkin ada) metode lain dariRectangle
.sumber
Saya pikir Anda mengerti semua yang dilakukan Antarmuka, tetapi Anda belum membayangkan situasi di mana Antarmuka berguna.
Jika Anda membuat instance, menggunakan dan melepaskan objek semua dalam lingkup sempit (misalnya, dalam satu panggilan metode), sebuah Interface tidak benar-benar menambahkan apa pun. Seperti yang Anda catat, kelas konkret dikenal.
Di mana Antarmuka berguna adalah ketika suatu objek perlu dibuat satu tempat dan dikembalikan ke penelepon yang mungkin tidak peduli dengan detail implementasi. Mari kita ubah contoh IBox Anda menjadi Shape. Sekarang kita dapat memiliki implementasi Shape seperti Rectangle, Circle, Triangle, dll. Implementasi metode getArea () dan getSize () akan sangat berbeda untuk setiap kelas beton.
Sekarang Anda dapat menggunakan pabrik dengan berbagai metode createShape (params) yang akan mengembalikan Bentuk yang sesuai tergantung pada params yang dilewati. Jelas, pabrik akan tahu tentang jenis Bentuk apa yang sedang dibuat, tetapi penelepon tidak akan memiliki untuk peduli apakah itu lingkaran, atau kotak, atau sebagainya.
Sekarang, bayangkan Anda memiliki berbagai operasi yang harus Anda lakukan pada bentuk Anda. Mungkin Anda perlu mengurutkannya berdasarkan area, mengatur semuanya ke ukuran baru, dan kemudian menampilkannya di UI. Semua Bentuk dibuat oleh pabrik dan kemudian dapat diteruskan ke kelas Sorter, Sizer, dan Tampilan dengan sangat mudah. Jika Anda perlu menambahkan kelas segi enam beberapa waktu di masa depan, Anda tidak perlu mengubah apa pun kecuali pabrik. Tanpa Antarmuka, menambahkan bentuk lain menjadi proses yang sangat berantakan.
sumber
Anda bisa melakukannya
dengan begitu Anda menggunakan objek ini sebagai Ibox dan Anda tidak peduli itu benar-benar
Rectangle
.sumber
Square
Anda akan memiliki masalah .... jika Anda mencoba melakukannya tanpa antarmuka, Anda tidak dapat menjamin ituSquare
danRectangle
memiliki metode yang sama ... ini dapat mengakibatkan mimpi buruk ketika Anda memiliki basis kode yang lebih besar ... Ingat, antarmuka mendefinisikan templat.MENGAPA INTERFACE ??????
Dimulai dengan seekor anjing. Secara khusus, pesek .
Pesek memiliki berbagai perilaku:
Dan Anda memiliki Labrador, yang juga memiliki serangkaian perilaku.
Kita bisa membuat beberapa pugs dan laboratorium:
Dan kita dapat memohon perilaku mereka:
Katakanlah saya menjalankan kandang anjing dan saya harus melacak semua anjing yang saya tempati. Saya perlu menyimpan pugs dan labrador saya di array terpisah :
Tapi ini jelas tidak optimal. Jika saya ingin menyimpan beberapa pudel juga, saya harus mengubah definisi Kennel saya untuk menambahkan array Pudel. Faktanya, saya membutuhkan array terpisah untuk setiap jenis anjing.
Wawasan: pugs dan labrador (dan pudel) adalah jenis anjing dan mereka memiliki perilaku yang sama. Yaitu, kita dapat mengatakan (untuk keperluan contoh ini) bahwa semua anjing dapat menggonggong, memiliki nama, dan mungkin memiliki ekor keriting atau tidak. Kita dapat menggunakan antarmuka untuk menentukan apa yang dapat dilakukan semua anjing, tetapi serahkan pada jenis anjing tertentu untuk menerapkan perilaku tertentu itu. Antarmuka mengatakan "ini adalah hal-hal yang dapat dilakukan semua anjing" tetapi tidak mengatakan bagaimana setiap perilaku dilakukan.
Kemudian saya sedikit mengubah kelas Pug dan Lab untuk menerapkan perilaku Dog. Kita dapat mengatakan bahwa Pug adalah Anjing dan Lab adalah seekor anjing.
Saya masih dapat membuat Instanate Pugs dan Labs seperti yang saya lakukan sebelumnya, tapi sekarang saya juga mendapatkan cara baru untuk melakukannya:
Ini mengatakan bahwa d1 bukan hanya seekor Anjing, tetapi secara khusus seekor Pug. Dan d2 juga adalah Anjing, khususnya Lab. Kita dapat memohon perilaku dan mereka bekerja seperti sebelumnya:
Di sinilah semua pekerjaan ekstra terbayar. Kelas Kennel menjadi lebih sederhana. Saya hanya perlu satu larik dan satu metode addDog. Keduanya akan bekerja dengan benda apa pun yang adalah anjing; yaitu objek yang mengimplementasikan antarmuka Anjing.
Berikut cara menggunakannya:
Pernyataan terakhir akan menampilkan: Spot Fido
Antarmuka memberi Anda kemampuan untuk menentukan serangkaian perilaku yang akan dimiliki oleh semua kelas yang mengimplementasikan antarmuka. Sebagai konsekuensinya, kita dapat mendefinisikan variabel dan koleksi (seperti array) yang tidak perlu tahu sebelumnya apa jenis objek spesifik yang akan mereka pegang, hanya saja mereka akan memegang objek yang mengimplementasikan antarmuka.
sumber
Contoh yang bagus tentang bagaimana antarmuka digunakan dalam kerangka kerja Koleksi. Jika Anda menulis fungsi yang membutuhkan a
List
, maka tidak masalah jika pengguna memasukkan aVector
atau aArrayList
atau aHashList
atau apa pun. Dan Anda dapat meneruskannyaList
ke fungsi apa pun yang memerlukanCollection
atauIterable
antarmuka juga.Ini membuat fungsi menjadi
Collections.sort(List list)
mungkin, terlepas dari bagaimanaList
penerapannya.sumber
Ini adalah alasan mengapa Pola Pabrik dan pola kreasi lainnya sangat populer di Jawa. Anda benar bahwa tanpa mereka Java tidak menyediakan mekanisme out of the box untuk memudahkan abstraksi instantiasi. Namun, Anda mendapatkan abstraksi di mana-mana di mana Anda tidak membuat objek dalam metode Anda, yang seharusnya menjadi sebagian besar kode Anda.
Sebagai tambahan, saya biasanya mendorong orang untuk tidak mengikuti mekanisme "IRealname" untuk penamaan antarmuka. Itu hal Windows / COM yang menempatkan satu kaki di kuburan notasi Hungaria dan benar-benar tidak perlu (Java sudah sangat diketik, dan seluruh titik memiliki antarmuka adalah untuk membuat mereka sebagian besar tidak dapat dibedakan dari tipe kelas mungkin).
sumber
Jangan lupa bahwa di kemudian hari Anda dapat mengambil kelas yang ada , dan membuatnya diterapkan
IBox
, dan kemudian akan tersedia untuk semua kode kotak-sadar Anda.Ini menjadi sedikit lebih jelas jika antarmuka diberi nama -able . misalnya
dll. (Skema penamaan tidak selalu berfungsi misalnya saya tidak yakin
Boxable
cocok di sini)sumber
Saya memperbarui jawabannya dengan fitur antarmuka baru, yang telah diperkenalkan dengan versi java 8 .
Dari halaman dokumentasi oracle pada ringkasan antarmuka :
Deklarasi antarmuka dapat berisi
Satu-satunya metode yang memiliki implementasi adalah metode default dan statis.
Penggunaan antarmuka :
Serializable
antarmuka mungkin atau mungkin tidak memiliki hubungan di antara mereka kecuali menerapkan antarmuka ituBeberapa pertanyaan SE terkait sehubungan dengan perbedaan antara kelas abstrak dan antarmuka dan gunakan kasus dengan contoh kerja:
Apa perbedaan antara antarmuka dan kelas abstrak?
Bagaimana seharusnya saya menjelaskan perbedaan antara Interface dan kelas Abstrak?
Lihat halaman dokumentasi untuk memahami fitur-fitur baru yang ditambahkan di java 8: metode default dan metode statis .
sumber
Tujuan dari antarmuka adalah abstraksi , atau decoupling dari implementasi.
Jika Anda memperkenalkan abstraksi dalam program Anda, Anda tidak peduli dengan kemungkinan implementasi. Anda tertarik pada apa yang bisa dilakukan dan bukan bagaimana , dan Anda menggunakan
interface
untuk mengekspresikan ini di Jawa.sumber
Jika Anda memiliki CardboardBox dan HtmlBox (keduanya mengimplementasikan IBox), Anda bisa meneruskan keduanya ke metode apa pun yang menerima IBox. Meskipun keduanya sangat berbeda dan tidak sepenuhnya dapat dipertukarkan, metode yang tidak mempedulikan "buka" atau "mengubah ukuran" masih dapat menggunakan kelas Anda (mungkin karena mereka peduli tentang berapa banyak piksel yang diperlukan untuk menampilkan sesuatu di layar).
sumber
Antarmuka tempat fetature ditambahkan ke java untuk memungkinkan pewarisan berganda. Pengembang Java meskipun saya menyadari bahwa memiliki banyak warisan adalah fitur "berbahaya", itulah sebabnya muncul dengan ide antarmuka.
multiple inheritance berbahaya karena Anda mungkin memiliki kelas seperti berikut:
Yang akan menjadi metode yang harus dipanggil saat kita gunakan
Semua masalah diselesaikan dengan antarmuka, karena Anda tahu Anda dapat memperluas antarmuka dan bahwa mereka tidak akan memiliki metode klasifikasi ... tentu saja kompilernya bagus dan memberi tahu Anda jika Anda tidak menerapkan metode, tetapi saya suka berpikir bahwa itu adalah efek samping dari ide yang lebih menarik.
sumber
Inilah pemahaman saya tentang keunggulan antarmuka. Koreksi saya jika saya salah. Bayangkan kita sedang mengembangkan OS dan tim lain sedang mengembangkan driver untuk beberapa perangkat. Jadi kami telah mengembangkan antarmuka StorageDevice. Kami memiliki dua implementasi (FDD dan HDD) yang disediakan oleh tim pengembang lain.
Kemudian kita memiliki kelas OperatingSystem yang dapat memanggil metode antarmuka seperti saveData hanya dengan melewatkan instance kelas yang mengimplementasikan antarmuka StorageDevice.
Keuntungannya di sini adalah kita tidak peduli dengan implementasi antarmuka. Tim lain akan melakukan pekerjaan itu dengan mengimplementasikan antarmuka StorageDevice.
sumber