Wie bereits in den Kommentaren und Antworten darauf hingewiesen: Es hängt alles davon ab, was Sie versuchen Modell dort.
Aber vor allem in Bezug auf die Absicht, die Sie erwähnt:
So sie nur für den Fall, Ich schaffe ich brauche immer eine Instanceof bedingte Anweisung zu verwenden.
Seien Sie vorsichtig damit. Sie sollten es vermeiden, das unterschiedliche Verhalten von Objekten abhängig von ihrem Typ zu modellieren. Dabei spielt es keine Rolle, ob die Typinformationen
- implizit verfügbar über
instanceof
prüfen
- explizit über ein Verfahren wie
boolean isMotorCycle()
, wie es in einem Kommentar vorgeschlagen
- explizit über so etwas wie ein
enum Type { ... }
und ein switch
über der Typ.
Sie alle leiden unter dem gleichen Problem: Wenn Sie eine neue Klasse/Typ Ihrer Hierarchie hinzufügen, dann müssen Sie alle Orte beschließen und zu aktualisieren, wo diese Art Informationen abgefragt wurde. Dies kann zu einem Alptraum werden.
Dort sind legitime Anwendungen für Typprüfungen. Aber wenn Sie mit dem Schreiben von Code am Ende, die häufig überprüft haben, wie diese
void recharge(Vehicle v) {
if (v instanceof ElectricCar) ((ElectricCar)v).attachPlug();
if (v instanceof GasolineCar) ((GasolineCar)v).fillFuel();
if (v instanceof Bike) ((Bike)v).getDriver().takeRest();
...
}
dann ist dies ein starker Hinweis darauf, dass etwas mit Ihrer Hierarchie falsch ist. Es kann sein, dass die Basisklasse, Vehicle
, einfach nicht stark genug ist. Im obigen Beispiel könnte man dann in Betracht ziehen, die recharge()
-Methode in die Klasse Vehicle
zu ziehen und sie einfach aufzurufen, wobei man sich auf die polymorphe Implementierung verlässt.
Es könnte im schlimmsten Fall auch sein, dass die Konzepte, die Sie zu modellieren versuchen, einfach zu unabhängig sind, um in einer einzigen Hierarchie kombiniert zu werden.
Sie haben erwähnt, dass Sie eine Kollisionserkennung für diese Objekte durchführen möchten. Das klingt wie Sie bereits eine Lösung wie diese Annäherung:
class Bike extends Vehicle {
@Override
void collideWith(Vehicle other) {
if (other instanceof Car) collideWithCar((Car)other);
if (other instanceof Segway) collideWithSegway((Segway)other);
...
}
}
Es gibt elegantere Lösungen dafür. Vielleicht möchten Sie über das Problem im Zusammenhang mit Double Dispatch lesen, und vielleicht werfen Sie einen Blick auf die Strategy Pattern.
Allgemeiner über die Frage, ob man „zu viele Klassen“ haben, gibt es einige allgemeine Regeln fo Daumen.
Einer von ihnen ist die Interface Segration Principle, die besagt, dass Sie serval Client-spezifische Schnittstellen erstellen sollten, anstatt einer großen Schnittstelle, die alles tut und daher sonst nicht verwandte Methoden kombiniert. Sie haben also nicht "zu viele Klassen", solange jeder von ihnen einen Zweck erfüllt. Man könnte sich fragen:
- Wer hat zwischen einem
GasolineCar
und einem ElectricCar
zu unterscheiden?
- Wer muss sich nur mit einer dieser Schnittstellen beschäftigen?
- Wenn sie erstrecken sich beide die gleiche Basisklasse: Wer wird die Basisklasse in der Lage zu nutzen (oder wird jeder irgendwie die konkrete Umsetzung wissen müssen?)
Ich interessiere mich für eine Art und Weise Sie verwenden wollen diese Klassen. – SMA
hängt alles davon ab, wie Sie sie verwenden werden. Bisher ist mit deiner Struktur nichts falsch. Und Sie können es nicht nur als Beispiel verwenden, sondern beispielsweise auch für Methoden wie boollean needsPetrol() ... canHavePassengers(), die Sie in den Unterklassen implementieren, anstatt die Kette von if instanceof-Anweisungen zu verwenden. – Zielu
Was versuchst du zu tun? – nom