Ich habe eine Basisklasse Base. Es hat zwei Unterklassen Sub1und Sub2. Jede Unterklasse verfügt über einige zusätzliche Methoden. Zum Beispiel Sub1hat Sandwich makeASandwich(Ingredients... ingredients)und Sub2hat boolean contactAliens(Frequency onFrequency).
Da diese Methoden unterschiedliche Parameter verwenden und völlig unterschiedliche Aufgaben ausführen, sind sie vollständig inkompatibel, und ich kann nicht einfach den Polymorphismus verwenden, um dieses Problem zu lösen.
Basebietet den größten Teil der Funktionalität, und ich habe eine große Sammlung von BaseObjekten. Alle BaseObjekte sind jedoch entweder ein Sub1oder ein Sub2, und manchmal muss ich wissen, um welche es sich handelt.
Es scheint eine schlechte Idee zu sein, Folgendes zu tun:
for (Base base : bases) {
if (base instanceof Sub1) {
((Sub1) base).makeASandwich(getRandomIngredients());
// ... etc.
} else { // must be Sub2
((Sub2) base).contactAliens(getFrequency());
// ... etc.
}
}
Also habe ich mir eine Strategie ausgedacht, um dies zu vermeiden, ohne zu zaubern. BaseJetzt hat diese Methoden:
boolean isSub1();
Sub1 asSub1();
Sub2 asSub2();
Und natürlich Sub1implementiert diese Methoden als
boolean isSub1() { return true; }
Sub1 asSub1(); { return this; }
Sub2 asSub2(); { throw new IllegalStateException(); }
Und Sub2setzt sie umgekehrt um.
Leider haben jetzt Sub1und Sub2diese Methoden eine eigene API. So kann ich das zum Beispiel weiter machen 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(); }
Wenn bekannt ist, dass das Objekt nur ein Objekt ist Base, sind diese Methoden nicht veraltet und können verwendet werden, um sich selbst in einen anderen Typ umzuwandeln, sodass ich die Methoden der Unterklasse aufrufen kann. In gewisser Weise erscheint mir das elegant, aber andererseits missbrauche ich veraltete Annotationen, um Methoden aus einer Klasse zu "entfernen".
Da eine Sub1Instanz wirklich eine Basis ist, ist es sinnvoll, Vererbung anstelle von Kapselung zu verwenden. Geht es mir gut? Gibt es einen besseren Weg, um dieses Problem zu lösen?
instanceofsind auf eine Weise, die viel Eingabe erfordert, fehleranfällig und machen es schwierig, weitere Unterklassen hinzuzufügen.
Sub1und Sub2kann nicht austauschbar verwendet werden, warum behandeln Sie sie dann als solche? Warum nicht Ihre "Sandwichmacher" und "Außerirdischen" getrennt nachverfolgen?