Apa pun yang mengimplementasikan I3 perlu mengimplementasikan I1 dan I2, dan objek dari kelas yang berbeda yang mewarisi I3 kemudian dapat digunakan secara bergantian (lihat di bawah), jadi apakah benar untuk memanggil I3 kosong? Jika demikian, apa yang akan menjadi cara yang lebih baik untuk arsitektur ini?
"Bundling" I1
dan I2
menjadi I3
penawaran yang bagus (?) Shortcut, atau semacam gula sintaks untuk manapun Anda ingin baik untuk dilaksanakan.
Masalah dengan pendekatan ini adalah bahwa Anda tidak dapat menghentikan pengembang lain dari penerapan I1
dan I2
berdampingan secara eksplisit , tetapi tidak bekerja dua arah - meskipun : I3
setara : I1, I2
, : I1, I2
tidak setara : I3
. Bahkan jika mereka identik secara fungsional, kelas yang mendukung keduanya I1
dan I2
tidak akan terdeteksi sebagai pendukung I3
.
Ini berarti Anda menawarkan dua cara untuk mencapai hal yang sama - "manual" dan "manis" (dengan gula sintaksis Anda). Dan itu dapat berdampak buruk pada konsistensi kode. Menawarkan 2 cara berbeda untuk mencapai hal yang sama di sini, di sana, dan di tempat lain menghasilkan 8 kemungkinan kombinasi :)
void foo() {
I1 something = new A();
something = new B();
something.SomeI1Function();
something.SomeI2Function(); // we can't do this without casting first
}
OKE, kamu tidak bisa. Tapi mungkin itu pertanda baik?
Jika I1
dan I2
menyiratkan tanggung jawab yang berbeda (jika tidak, tidak perlu memisahkan mereka di tempat pertama), maka mungkin foo()
salah untuk mencoba dan something
melakukan dua tanggung jawab yang berbeda sekaligus?
Dengan kata lain, bisa jadi itu foo()
sendiri melanggar prinsip Tanggung Jawab Tunggal, dan fakta bahwa itu membutuhkan pemeriksaan tipe casting dan runtime untuk menariknya adalah sebuah bendera merah yang mengkhawatirkan kita tentang hal itu.
EDIT:
Jika Anda bersikeras memastikan bahwa foo
dibutuhkan sesuatu yang mengimplementasikan I1
dan I2
, Anda dapat meneruskannya sebagai parameter terpisah:
void foo(I1 i1, I2 i2)
Dan mereka bisa menjadi objek yang sama:
foo(something, something);
Apa foo
peduli jika mereka adalah contoh yang sama atau tidak?
Tetapi jika itu benar-benar peduli (mis. Karena mereka tidak berkewarganegaraan), atau Anda hanya berpikir ini terlihat jelek, seseorang dapat menggunakan obat generik sebagai gantinya:
void Foo<T>(T something) where T: I1, I2
Sekarang kendala generik menangani efek yang diinginkan sambil tidak mencemari dunia luar dengan apa pun. Ini adalah C # idiomatis, berdasarkan pada pemeriksaan waktu kompilasi, dan secara keseluruhan terasa lebih tepat.
Saya melihat I3 : I2, I1
agak sebagai upaya untuk meniru jenis serikat dalam bahasa yang tidak mendukungnya di luar kotak (C # atau Java tidak, sedangkan jenis serikat ada dalam bahasa fungsional).
Mencoba meniru suatu konstruksi yang tidak terlalu didukung oleh bahasa sering kali kikuk. Demikian pula, di C # Anda dapat menggunakan metode ekstensi dan antarmuka jika Anda ingin meniru mixin . Bisa jadi? Iya. Ide bagus? Saya tidak yakin.