Saya memiliki kelas dasar Base
,. Ini memiliki dua subclass, Sub1
dan Sub2
. Setiap subkelas memiliki beberapa metode tambahan. Misalnya, Sub1
memiliki Sandwich makeASandwich(Ingredients... ingredients)
, dan Sub2
memilikiboolean contactAliens(Frequency onFrequency)
.
Karena metode ini mengambil parameter yang berbeda dan melakukan hal yang sama sekali berbeda, mereka sepenuhnya tidak kompatibel, dan saya tidak bisa menggunakan polimorfisme untuk menyelesaikan masalah ini.
Base
menyediakan sebagian besar fungsionalitas, dan saya memiliki banyak koleksi Base
objek. Namun, semua Base
benda adalah a Sub1
atau a Sub2
, dan kadang-kadang saya perlu tahu yang mana.
Sepertinya ide yang buruk untuk melakukan hal berikut:
for (Base base : bases) {
if (base instanceof Sub1) {
((Sub1) base).makeASandwich(getRandomIngredients());
// ... etc.
} else { // must be Sub2
((Sub2) base).contactAliens(getFrequency());
// ... etc.
}
}
Jadi saya datang dengan strategi untuk menghindari ini tanpa casting. Base
sekarang memiliki metode ini:
boolean isSub1();
Sub1 asSub1();
Sub2 asSub2();
Dan tentu saja, Sub1
menerapkan metode ini sebagai
boolean isSub1() { return true; }
Sub1 asSub1(); { return this; }
Sub2 asSub2(); { throw new IllegalStateException(); }
Dan Sub2
mengimplementasikannya dengan cara yang berlawanan.
Sayangnya, sekarang Sub1
dan Sub2
memiliki metode ini di API mereka sendiri. Jadi saya bisa melakukan ini, misalnya, pada Sub1
.
/** no need to use this if object is known to be Sub1 */
@Deprecated
boolean isSub1() { return true; }
/** no need to use this if object is known to be Sub1 */
@Deprecated
Sub1 asSub1(); { return this; }
/** no need to use this if object is known to be Sub1 */
@Deprecated
Sub2 asSub2(); { throw new IllegalStateException(); }
Dengan cara ini, jika objek diketahui hanya a Base
, metode ini tidak ditinggalkan, dan dapat digunakan untuk "melemparkan" dirinya ke jenis yang berbeda sehingga saya dapat memanggil metode subclass di atasnya. Ini tampaknya elegan bagi saya, tetapi di sisi lain, saya agak menyalahgunakan anotasi usang sebagai cara untuk "menghapus" metode dari kelas.
Karena sebuah Sub1
instance benar - benar sebuah Base, masuk akal untuk menggunakan warisan daripada enkapsulasi. Apakah yang saya lakukan baik? Apakah ada cara yang lebih baik untuk menyelesaikan masalah ini?
instanceof
, dengan cara yang membutuhkan banyak pengetikan, rentan kesalahan, dan membuatnya sulit untuk menambahkan lebih banyak subkelas.
Sub1
dan Sub2
tidak dapat digunakan secara bergantian, mengapa Anda memperlakukannya seperti itu? Mengapa tidak melacak 'pembuat sandwich' dan 'alien-contacters' Anda secara terpisah?