Ich habe eine Basisklasse Base
. Es hat zwei Unterklassen Sub1
und Sub2
. Jede Unterklasse verfügt über einige zusätzliche Methoden. Zum Beispiel Sub1
hat Sandwich makeASandwich(Ingredients... ingredients)
und Sub2
hat 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.
Base
bietet den größten Teil der Funktionalität, und ich habe eine große Sammlung von Base
Objekten. Alle Base
Objekte sind jedoch entweder ein Sub1
oder 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. Base
Jetzt hat diese Methoden:
boolean isSub1();
Sub1 asSub1();
Sub2 asSub2();
Und natürlich Sub1
implementiert diese Methoden als
boolean isSub1() { return true; }
Sub1 asSub1(); { return this; }
Sub2 asSub2(); { throw new IllegalStateException(); }
Und Sub2
setzt sie umgekehrt um.
Leider haben jetzt Sub1
und Sub2
diese 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 Sub1
Instanz 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?
instanceof
sind auf eine Weise, die viel Eingabe erfordert, fehleranfällig und machen es schwierig, weitere Unterklassen hinzuzufügen.
Sub1
und Sub2
kann nicht austauschbar verwendet werden, warum behandeln Sie sie dann als solche? Warum nicht Ihre "Sandwichmacher" und "Außerirdischen" getrennt nachverfolgen?