Cara menerapkan hanya sebagian dari antarmuka

14

Saat berkembang dalam OOP, terkadang antarmuka / kontrak diberikan oleh perpustakaan yang tidak dapat Anda ubah. Sebut saja antarmuka ini J.

Sekarang Anda memiliki objek kelas A yang mengkonsumsi objek yang mengimplementasikan antarmuka ini. Di dalam Hanya diperlukan sebagian kecil dari definisi antarmuka. Beberapa kelas objek dibuat oleh saya selama proyek (sebut saja salah satu dari mereka tipe D), jadi ada overhead dalam implementasi segala sesuatu di dalam antarmuka J.

Saya ingin mengimplementasikan subset dari fungsionalitas di antarmuka J, tetapi solusi saya sejauh ini tidak memuaskan saya:

  • menerapkan setiap aspek J dan kemudian melemparkan "notImplementedExceptions" salah informasi pengguna objek saya: akan terlihat objek tipe D saya sesuai dengan antarmuka J, tetapi mereka tidak - dan konsumen lain dari objek saya (yang menerima objek yang mengimplementasikan antarmuka J) tidak dapat mengandalkan integritas dari objek saya.
  • Menerapkan antarmuka yang baru didefinisikan melarang saya menggunakan objek yang hanya mengimplementasikan antarmuka J, meskipun antarmuka J sepenuhnya kompatibel dengan antarmuka saya sendiri.
  • Membiarkan objek kustom saya mengimplementasikan antarmuka J akan membuat overhead yang signifikan, karena mereka tidak memerlukan semua fungsi ini.

Ketika saya dapat mengubah antarmuka J, saya akan membuat "super-interface" K yang memiliki subset ini dari fungsi antarmuka J, dan membuat antarmuka J mewarisi dari antarmuka K. Tapi saya tidak dapat mengubah antarmuka J.

Apa solusi berorientasi objek untuk masalah ini? Apakah solusi terbaik masih menerapkan antarmuka J "just"? Atau adakah cara OOP untuk "superclass" suatu antarmuka tanpa mengubahnya?

vstrien
sumber
1
Lihat bagaimana * Kelas adaptor dalam Swing melakukan ini.

Jawaban:

9

jika Anda tidak mengontrol antarmuka J, Anda macet.

Anda dapat, untuk kejelasan, mengimplementasikan antarmuka Anda sendiri dan antarmuka J, dan menggunakan subJ dalam kode Anda sendiri untuk memperjelas bahwa metode tambahan dalam antarmuka J tidak diperlukan, tetapi saya tidak berpikir itu benar-benar menguntungkan Anda.

jika memungkinkan, terapkan seluruh antarmuka J sepenuhnya

jika memungkinkan, hubungi pemilik antarmuka J dan minta dia untuk mengubahnya agar lebih sesuai dengan tujuan Anda

Steven A. Lowe
sumber
2
Sebagai kompromi: Anda dapat meminta pemilik antarmuka J untuk mewarisi bentuk antarmuka SubJ yang lebih kecil.
k3b
27

Inti penerapan antarmuka adalah untuk menyediakan kontrak yang tegas antara penelepon dan callee yang tidak pernah berubah sementara detail implementasi dapat bervariasi.

Dengan mengimplementasikan antarmuka J Anda memberi tahu dunia luar apa yang dapat Anda lakukan.

Jika Anda tidak perlu setengah dari apa yang dilakukan J maka antarmuka harus benar-benar dibagi lagi karena tidak sekecil mungkin, atau Anda harus NotImplementedExceptionmenggunakan metode dan properti yang tidak Anda butuhkan. Namun, ini bukan solusi terbaik karena mengacaukan harapan orang tentang apa yang dapat dilakukan kode Anda.

ChrisF
sumber
5

Jika kelas A konsumen Anda tidak memerlukan semua antarmuka J, maka saya sarankan membuat antarmuka baru (sebut saja K), yang secara komprehensif menjelaskan semua yang diperlukan.

Ini memberikan sinyal yang jelas kepada siapa pun yang menggunakan kelas A tentang apa sisi kontrak mereka. Dengan demikian meningkatkan peluang penggunaan kembali. Jika seseorang perlu menyediakan objek yang mengimplementasikan antarmuka yang besar dan kompleks, untuk melakukan sesuatu yang relatif sederhana, mereka mungkin akan berakhir menulis apa pun yang dilakukan kelas A sendiri.

Untuk memungkinkan kelas A mengkonsumsi objek yang mengimplementasikan antarmuka J saja, Anda bisa menyediakan kelas pembungkus yang mengimplementasikan antarmuka K dan meneruskan semua panggilan yang sesuai ke anggota antarmuka J.

Paul Butcher
sumber
3

Sementara saya setuju dengan jawaban yang ada yang mengatakan Anda benar-benar perlu mengimplementasikan J sepenuhnya (dengan pengecualian untuk metode yang tidak diterapkan) atau tidak sama sekali, solusi yang mungkin adalah sebagai berikut:

  • Buat antarmuka K yang lebih kecil yang merupakan himpunan bagian dari J dan mengimplementasikan metode yang diperlukan.
  • Buat pembungkus untuk A yang menerima objek yang mengimplementasikan J dan K.
  • Dalam kasus lulus dalam J, cukup dorong ke instance A.
  • Dalam kasus lulus dalam K, instantiate implementasi J anonim, kabel hanya metode dari K ke J yang ada. Berikan hasilnya ke instance A.

Harap dicatat bahwa ini adalah solusi yang jelek, karena membutuhkan pembungkus yang menerima banyak hal yang pada dasarnya adalah hal yang sama. Tapi itu mencapai hal berikut:

  • Tidak ada perubahan pada J atau A.
  • Tidak ada implementasi "terbuka" dari J yang tidak lengkap.

Jika bahasa OO Anda tidak memungkinkan instantiasi antarmuka anonim, Anda dapat membuat implementasi tiruan antarmuka dan instantiate itu.

Deckard
sumber
1

Berapa lama waktu yang dibutuhkan untuk mengimplementasikan seluruh antarmuka?

Jika Anda membutuhkan waktu cukup lama, ini menunjukkan masalah desain, dan saya akan menyarankan Anda (seperti yang dilakukan Steven A. sebelum saya) untuk menghubungi pemilik dan melihat apakah itu dapat diubah di masa mendatang.

Apakah Anda menggunakan antarmuka dalam kode Anda sendiri, terlepas dari perpustakaan antarmuka?

Seperti yang disarankan Steven A., Anda dapat menggunakan antarmuka Anda sendiri karena Anda ingin melihatnya dalam kode Anda sendiri. Setidaknya ini menjaga kode in-house Anda tetap bersih. Anda juga dapat mengirim ini ke pemilik sebagai antarmuka yang Anda harapkan akan ditemukan. Mungkin dia setuju dengan Anda, atau mungkin dia bisa menjelaskan kepada Anda mengapa antarmuka tidak boleh terpecah.

Apakah implementasi Anda memerlukan anggota antarmuka yang tidak terpakai?

Jika Anda dapat mengharapkan mereka tidak pernah dipanggil karena mereka 'tidak didukung', saya lebih suka menggunakan NotSupportedException. Ini memberikan indikasi yang jelas bahwa Anda tidak akan pernah mendukung antarmuka ini, daripada Anda tidak mengimplementasikannya.

Steven Jeuris
sumber
Gagasan bagus untuk menggunakannya NotSupportedExceptiontidak memperjelas bahwa Anda tidak mendukung metode itu.
ChrisF
@ ChrisF: Saya hanya menggunakan NotImplementedExceptionkode produksi, di mana saya akan menulis "TODO: Implementasikan ini" Sayangnya, mereka tidak muncul di daftar tugas Visual Studio . Namun dalam praktiknya, saya hampir tidak meninggalkan metode yang tidak diterapkan selama lebih dari dua hari. Resharper juga menunjukkan pengecualian itu dalam huruf tebal (setidaknya dengan pengaturan saya). :)
Steven Jeuris
0

Menerapkan apa yang Anda butuhkan, dan melemparkan pengecualian NoImplementedException pada yang lain.

Ini masalah penggunaan. Jika Anda tidak menggunakan antarmuka, atau Anda tahu kode Anda tidak akan menggunakan antarmuka, maka jangan menginvestasikan waktu untuk hal ini, karena Anda tidak perlu menginvestasikan waktu pada kode yang berlebihan.

Kerjakan tugas yang ada, dan ikuti jejak yang baik untuk diikuti orang lain jika mereka ingin menggunakan antarmuka.

Banyak antarmuka di Jawa tidak diimplementasikan secara penuh.

Ini adalah pendekatan Apache untuk berbagai hal: http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/NotImplementedException.html

Nama tampilan
sumber
Mungkin berdebat mengapa Anda percaya ini adalah solusi yang tepat. Ini tidak menambah pertanyaan.
Steven Jeuris
tidak perlu untuk mengimplementasikan semuanya, karena tidak ada kebutuhan nyata untuk menjelaskan semuanya. jika itu masalahnya, beberapa bagian dari antarmuka itu berlebihan, dia akan segera mengambilnya.
Nama Tampilan