Saya merancang program OOP kecil saya sendiri untuk mensimulasikan Vampir, Serigala, Manusia dan Truk dan saya mencoba menerapkan pemahaman saya sendiri yang terbatas tentang Antarmuka.
( Saya masih abstrak di sini dan belum mengimplementasikan kode, jadi ini pertanyaan desain OOP ... saya rasa!)
Apakah saya benar dalam mencari 'perilaku umum' antara kelas-kelas ini dan mengimplementasikannya sebagai antarmuka ?
Misalnya, Vampir dan Serigala menggigit ... jadi haruskah saya memiliki antarmuka gigitan?
public class Vampire : Villain, IBite, IMove, IAttack
Demikian juga untuk Truk ...
public class Truck : Vehicle, IMove
Dan untuk Manusia ...
public class Man : Human, IMove, IDead
Apakah pemikiran saya ada di sini? (Hargai bantuan Anda)
object-oriented
interfaces
pengguna3396486
sumber
sumber
IEnumerable
,IEquatable
, dllJawaban:
Secara umum Anda ingin memiliki antarmuka untuk karakteristik umum clasess Anda.
Saya setengah setuju dengan @Robert Harvey dalam komentar, yang mengatakan bahwa biasanya antarmuka mewakili fitur kelas yang lebih abstrak. Namun demikian, saya menemukan mulai dari contoh yang lebih konkret cara yang baik untuk mulai berpikir abstrak.
Sementara contoh Anda secara teknis benar (yaitu ya, baik vampir dan serigala menggigit, sehingga Anda dapat memiliki antarmuka untuk itu), ada pertanyaan tentang relevansi. Setiap objek memiliki ribuan karakteristik (mis. Hewan mungkin memiliki bulu, dapat berenang, dapat memanjat pohon, dan sebagainya). Apakah Anda akan membuat antarmuka untuk semuanya? Sangat kecil kemungkinannya.
Anda biasanya ingin antarmuka untuk hal-hal yang masuk akal untuk dikelompokkan dalam suatu aplikasi secara keseluruhan. Misalnya, jika Anda membuat game, Anda dapat memiliki larik objek IMove dan memperbarui posisinya. Jika Anda tidak ingin melakukan itu, memiliki antarmuka IMove sangat tidak berguna.
Intinya, jangan over engineer. Anda perlu berpikir tentang bagaimana Anda akan menggunakan antarmuka itu, dan 2 kelas yang memiliki metode yang sama bukanlah alasan yang cukup baik untuk membuat antarmuka.
sumber
IBite
tidak terlalu berguna, tetapi Anda mungkin inginIAttack
agar Anda dapat mengatasi semua hal yang membuat serangan, atauIUpdate
agar Anda dapat menjalankan pembaruan untuk semuanya, atauIPhysicsEnabled
agar Anda dapat menerapkan fisika pada mereka, dll.Sepertinya Anda sedang membuat banyak antarmuka metode tunggal . Ini bagus di permukaannya tetapi perlu diingat bahwa antarmuka tidak dimiliki oleh kelas / es yang mengimplementasikannya. Mereka dimiliki oleh klien yang menggunakannya. Klien memutuskan apakah sesuatu perlu sesuatu yang bisa bergerak dan menyerang.
Jika saya memiliki
Combat
kelas denganfight()
metode, metode itu mungkin perlu memanggil keduanyamove()
danattack()
pada objek yang sama. Itu sangat menyarankan perlunyaICombatant
antarmuka yangfight()
dapat memanggilmove()
danattack()
melalui. Ini lebih bersih daripadafight()
mengambilIAttack
objek dan melemparkannyaIMove
untuk melihat apakah benda itu juga bisa bergerak.Itu tidak berarti Anda juga tidak dapat memiliki
IMove
IAttack
antarmuka. Saya hanya berharap Anda tidak membuatnya tanpa klien membutuhkannya. Sebaliknya, jika tidak ada klien yang perlu membuat objek bergerak dan menyerang makaICombatant
tidak diperlukan.Cara sederhana dalam memandang antarmuka sering kali hilang karena orang suka mengikuti contoh. Antarmuka pertama yang kami temukan adalah di perpustakaan. Sayangnya, perpustakaan tidak tahu apa itu klien mereka. Jadi mereka hanya bisa menebak kebutuhan klien mereka. Bukan contoh terbaik untuk diikuti.
sumber
Pertimbangkan apakah akan umum untuk memiliki koleksi objek dengan kombinasi kemampuan yang berbeda, dan apakah kode mungkin ingin melakukan tindakan terhadap item-item itu, dalam koleksi, yang mendukungnya . Jika demikian, dan jika ada "perilaku default" yang masuk akal untuk objek yang tidak memiliki dukungan yang berguna untuk beberapa tindakan, mungkin bermanfaat untuk memiliki antarmuka yang diimplementasikan oleh berbagai kelas, bukan hanya mereka yang dapat berperilaku bermanfaat.
Sebagai contoh, anggaplah hanya beberapa jenis makhluk yang dapat memiliki Woozles, dan seseorang ingin makhluk seperti itu memiliki
NumerOfWoozles
properti. Jika properti seperti itu berada di antarmuka yang hanya diterapkan oleh makhluk yang dapat memiliki Woozles, maka kode yang ingin menemukan jumlah total Woozles yang dipegang oleh kumpulan makhluk dari jenis campuran harus mengatakan sesuatu seperti:Namun, jika WoozleCount adalah anggota Creature / ICreature, meskipun beberapa subtipe akan mengesampingkan implementasi WoozleCount default Creature yang selalu mengembalikan nol, kode dapat disederhanakan menjadi:
Sementara beberapa orang mungkin kecewa dengan gagasan bahwa setiap makhluk menerapkan properti WoozleCount yang benar-benar hanya berguna untuk beberapa subtipe, properti itu akan bermakna untuk semua jenis, apakah itu akan berguna atau tidak dengan item yang diketahui jenisnya, dan saya akan menganggap antarmuka "kitchen sink" kurang berbau kode daripada operator trycast.
sumber