Sebagai contoh:
Katakanlah saya memiliki kelas A
, B
, C
. Saya memiliki dua antarmuka, sebut saja IAnimal
dan IDog
. IDog
mewarisi dari IAnimal
. A
dan B
yang IDog
s, sementara C
tidak, tapi itu adalah IAnimal
.
Bagian yang penting adalah IDog
tidak menyediakan fungsionalitas tambahan. Ini hanya digunakan untuk memungkinkan A
dan B
, tetapi tidak C
, untuk diteruskan sebagai argumen untuk metode tertentu.
Apakah ini praktik buruk?
object-oriented
interfaces
Kendall Frey
sumber
sumber
IAnimal
danIDog
yang nama tautologi mengerikan!MyProject.Data.IAnimal
danMyProject.Data.Animal
lebih baik daripadaMyProject.Data.Interfaces.Animal
danMyProject.Data.Implementations.Animal
Interface
atauImplementation
, apakah dalam awalan berulang atau namespace baik, itu adalah tautologi baik cara dan melanggar KERING.Dog
hanya itu yang harus Anda pedulikan.PitBull extends Dog
tidak perlu redundansi implementasi, kata ituextends
memberitahu saya semua yang perlu saya ketahui, baca tautan yang saya posting di komentar asli saya.Jawaban:
Antarmuka yang tidak memiliki anggota atau memiliki anggota yang sama persis dengan antarmuka lain yang diwarisi dari antarmuka yang sama yang disebut Marker Interface dan Anda menggunakannya sebagai penanda.
Ini bukan praktik yang buruk tetapi antarmuka dapat diganti dengan atribut (penjelasan) jika bahasa yang Anda gunakan mendukungnya.
Saya yakin dapat mengatakan bahwa ini bukan praktik yang buruk karena saya telah melihat pola "Marker Interface" penggunaan berat di Proyek Orchard
Berikut adalah contoh dari proyek Orchard.
Silakan merujuk ke Penanda Antarmuka .
sumber
C
metode yang mengharapkanIDog
.Kennel
kelas yang menyimpan daftarIDog
s.Ya, ini praktik buruk di hampir setiap bahasa.
Jenis tidak ada di sana untuk menyandikan data; mereka adalah bantuan untuk membuktikan bahwa data Anda pergi ke mana ia harus pergi dan berperilaku seperti itu perlu berperilaku. Satu-satunya alasan untuk sub-tipe adalah jika perilaku polimorfik berubah (dan tidak selalu demikian).
Karena tidak ada pengetikan, apa yang bisa dilakukan IDog tersirat. Satu programmer memikirkan satu hal, yang lain berpikir hal lain dan hal-hal rusak. Atau hal-hal yang diwakilinya meningkat karena Anda membutuhkan kontrol berbutir halus.
[edit: klarifikasi]
Maksud saya adalah Anda melakukan beberapa logika berdasarkan antarmuka. Mengapa beberapa metode hanya dapat bekerja dengan anjing dan hewan lainnya? Perbedaan itu adalah kontrak yang tersirat karena tidak ada anggota aktual yang menyediakan perbedaan; tidak ada data aktual dalam sistem. Satu-satunya perbedaan adalah antarmuka (oleh karena itu komentar 'tidak mengetik'), dan apa artinya akan berbeda antara programmer. [/ edit]
Bahasa tertentu menyediakan mekanisme sifat di mana ini tidak terlalu buruk tetapi mereka cenderung fokus pada kemampuan, bukan perbaikan. Saya memiliki sedikit pengalaman dengan mereka sehingga tidak dapat berbicara dengan praktik terbaik di sana. Dalam C ++ / Java / C # though ... not good.
sumber
Kennel
kelas yang menyimpan daftarIDog
s.Saya hanya tahu C # dengan baik, jadi saya tidak bisa mengatakan ini untuk pemrograman OO secara umum, tetapi sebagai contoh C #, jika Anda perlu mengkategorikan kelas opsi yang jelas adalah antarmuka, enum properti atau atribut khusus. Biasanya saya akan memilih antarmuka apa pun yang dipikirkan orang lain.
sumber
Tidak ada yang salah dengan memiliki antarmuka yang mewarisi antarmuka lain tanpa menambahkan anggota baru, jika semua implementasi dari antarmuka yang terakhir diharapkan dapat melakukan hal - hal yang beberapa implementasi dari yang sebelumnya mungkin tidak berguna . Memang, ini adalah pola yang baik dimana IMHO seharusnya lebih banyak digunakan dalam hal-hal seperti .net Framework, terutama karena seorang pelaksana yang kelasnya secara alami akan memenuhi kendala yang tersirat oleh antarmuka yang lebih diturunkan dapat menunjukkan bahwa hanya dengan menerapkan antarmuka yang lebih diturunkan. , tanpa harus mengubah kode atau deklarasi anggota-implementasi.
Sebagai contoh, misalkan saya memiliki antarmuka:
Suatu implementasi
IImmutableFoo.AsImmutable()
akan diharapkan untuk mengembalikan dirinya sendiri; implementasi kelas yang bisa berubahIMaybeMutableFoo.AsImmutable()
akan diharapkan untuk mengembalikan objek baru yang sangat tidak dapat diubah yang berisi snapshot data. Sebuah rutinitas yang ingin menyimpan snapshot data yang disimpan dalam suatuIMaybeMutableFoo
dapat menawarkan kelebihan:Dalam kasus di mana kompiler tidak tahu bahwa benda yang akan disimpan adalah
IImmutableFoo
, ia akan memanggilAsImmutable()
. Fungsi harus kembali dengan cepat jika item sudah tidak dapat diubah, tetapi panggilan fungsi melalui antarmuka masih membutuhkan waktu. Jika kompiler tahu bahwa item tersebut sudah merupakanIImmutableFoo
, ia dapat melewati pemanggilan fungsi yang tidak perlu.sumber