Saya merancang antarmuka dengan dua metode terkait, mirip dengan ini:
public interface ThingComputer {
default Thing computeFirstThing() {
return computeAllThings().get(0);
}
default List<Thing> computeAllThings() {
return ImmutableList.of(computeFirstThing());
}
}
Sekitar setengah implementasi hanya akan menghitung satu hal, sedangkan setengah lainnya dapat menghitung lebih.
Apakah ini memiliki preseden dalam kode Java 8 yang banyak digunakan? Saya tahu Haskell melakukan hal serupa di beberapa jenis kacamata ( Eq
misalnya).
Keuntungannya adalah saya harus menulis kode yang jauh lebih sedikit daripada jika saya memiliki dua kelas abstrak ( SingleThingComputer
dan MultipleThingComputer
).
The downside adalah bahwa implementasi kosong mengkompilasi tetapi meledak saat runtime dengan StackOverflowError
. Dimungkinkan untuk mendeteksi rekursi timbal balik dengan a ThreadLocal
dan memberikan kesalahan yang lebih bagus, tetapi itu menambah biaya tambahan pada kode non-kereta.
sumber
throw new Error();
atau sesuatu yang bodoh, hanya saja antarmuka itu sendiri tidak boleh memiliki kontrak rapuh melaluidefault
metode.abstract
ada untuk memaksa mereka menyelesaikannya.Jawaban:
TL; DR: jangan lakukan ini.
Apa yang Anda tunjukkan di sini adalah kode rapuh.
Antarmuka adalah kontrak. Dikatakan "terlepas dari objek apa yang Anda dapatkan, ia dapat melakukan X dan Y." Seperti yang tertulis, antarmuka Anda tidak X atau Y karena dijamin menyebabkan stack overflow.
Melempar Kesalahan atau subkelas menunjukkan kesalahan parah yang tidak boleh ditangkap:
Lebih jauh, VirtualMachineError , kelas induk StackOverflowError , mengatakan ini:
Program Anda seharusnya tidak peduli dengan sumber daya JVM . Itu adalah pekerjaan JVM. Membuat program yang menyebabkan kesalahan JVM sebagai bagian dari operasi normal buruk. Ini menjamin program Anda akan macet, atau memaksa pengguna antarmuka ini untuk menjebak kesalahan yang seharusnya tidak perlu diperhatikan.
Anda mungkin mengenal Eric Lippert dari upaya seperti emeritus "anggota komite desain bahasa C #". Dia berbicara tentang fitur bahasa yang mendorong orang menuju kesuksesan atau kegagalan: sementara ini bukan fitur bahasa atau bagian dari desain bahasa, maksudnya sama-sama valid ketika datang ke mengimplementasikan antarmuka atau menggunakan objek.
Sumber: C ++ dan Pit Of Despair
Memiliki antarmuka melempar secara
StackOverflowError
default mendorong pengembang ke Pit of Despair dan merupakan ide yang buruk . Sebaliknya, dorong pengembang ke Pit of Success . Buatlah mudah untuk menggunakan antarmuka Anda dengan benar dan tanpa menabrak JVM.Mendelegasikan antara metode tidak masalah di sini. Namun, ketergantungan harus berjalan satu arah. Saya suka memikirkan delegasi metode seperti grafik terarah . Setiap metode adalah simpul pada grafik. Setiap kali suatu metode memanggil metode lain, gambarkan tepi dari metode pemanggilan ke metode yang dipanggil.
Jika Anda menggambar grafik dan memperhatikannya adalah siklik, itu adalah bau kode. Itu adalah potensi untuk mendorong pengembang di Pit of Despair. Perhatikan bahwa itu tidak boleh dilarang secara kategoris, hanya saja seseorang harus berhati-hati . Algoritma rekursif secara khusus akan memiliki siklus dalam grafik panggilan: itu bagus. Dokumentasikan dan peringatkan pengembang. Jika tidak berulang, cobalah untuk memutus siklus itu. Jika Anda tidak bisa, cari tahu input apa yang mungkin menyebabkan stack overflow dan mitigasi atau dokumentasikan sebagai kasus terakhir jika tidak ada yang lain yang berfungsi.
sumber