У мене є базовий клас, Base
. Він має два підкласи Sub1
та Sub2
. Кожен підклас має деякі додаткові методи. Наприклад, Sub1
має Sandwich makeASandwich(Ingredients... ingredients)
і Sub2
має boolean contactAliens(Frequency onFrequency)
.
Оскільки ці методи приймають різні параметри і роблять абсолютно різні речі, вони абсолютно несумісні, і я не можу просто використати поліморфізм для вирішення цієї проблеми.
Base
забезпечує більшу частину функціональності, і у мене є велика колекція Base
об'єктів. Однак усі Base
об’єкти є або a, Sub1
або Sub2
іноді мені потрібно знати, що вони є.
Це здається поганою ідеєю зробити наступне:
for (Base base : bases) {
if (base instanceof Sub1) {
((Sub1) base).makeASandwich(getRandomIngredients());
// ... etc.
} else { // must be Sub2
((Sub2) base).contactAliens(getFrequency());
// ... etc.
}
}
Тому я придумав стратегію уникнути цього без кастингу. Base
тепер є такі методи:
boolean isSub1();
Sub1 asSub1();
Sub2 asSub2();
І звичайно, Sub1
реалізує ці методи як
boolean isSub1() { return true; }
Sub1 asSub1(); { return this; }
Sub2 asSub2(); { throw new IllegalStateException(); }
І Sub2
реалізує їх протилежним чином.
На жаль, зараз Sub1
і Sub2
є ці методи у власному API. Тож я можу це зробити, наприклад, на 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(); }
Таким чином, якщо об'єкт, як відомо, є лише a Base
, ці методи не є застарілими, і їх можна використовувати для того, щоб "передати" інший тип, щоб я міг викликати на ньому методи підкласу. Мені це здається елегантним, але, з іншого боку, я якось зловживаю Застареними примітками як способом "видалити" методи з класу.
Оскільки Sub1
екземпляр насправді є базовим, має сенс використовувати спадкування, а не інкапсуляцію. Це те, що я роблю добре? Чи є кращий спосіб вирішити цю проблему?
instanceof
, таким чином, вимагаючи багато введення тексту, схильний до помилок і ускладнює додавання більше підкласів.
Sub1
і Sub2
не можуть бути використані як взаємозамінні, то чому ви ставитися до них як такої? Чому б не відслідковувати своїх «бутербродників» та «інопланетян» окремо?