Achim Peters
2008-05-16 11:02:00 UTC
Hi,
ich bin nach ein paar Jahren verhaltener Pause wieder massiv beim OO (in
Java) aber OO-design-technisch etwas aus der Übung, und da hab' ein gern
emal ein Problem(chen), was in einer Compile-Fehlermeldung endet.
Die Meldung ist mir klar, ich weiß, warum sie kommen muß, und ich weiß,
wie ich sie umgehe. Ich möchte sie aber _elegant_ wegbekommen, und sei
es, dass ich dafür ein anderes Klassen-Design wählen muss. Da es somit
eine Designfrage ist, wähle ich ein beispielhaftes, leichter
darzustellendes Problem, das m. E. die konkreten Abhängigkeiten
hinreichend widerspiegelt.
Es gibt Fahrzeuge F, die manchmal repariert werden müssen, und
spezialisierte Reparatur-Werkstätten W pro Fahrzeughersteller. Wer eine
Reparatur in Auftrag geben will, hat ein konkretes Fahrzeug an der Hand,
er weiß aber nicht, welcher Reparatur-Firmen-Typ zuständig ist (eine
Mercedes-Werkstatt für einen 500SL und A-Klasse, Opel für Manta und
Vectra, etc.) Das ist aber rauszubekommen (z. B. weiß das ein Guru).
Jedefalls erhält der Fzg-Besitzer eine Instanz einer von W abgeleiteten
Klasse und die möchte er gerne mit repariere(meinAuto) aufrufen.
Die Klasse W habe ich jetzt als abstrakte Oberklasse aller
Reparaturwerkstättentypen definiert (weil der Guru einfach eine
zuständige "Werkstatt" liefert) und die Klasse F als abstrakte
Oberklasse aller Fahrzeugmarken definiert (weil eine Werkstatt allgemein
ein "F(ahrzeug)" repariert, Z. B.
public abstract class F ...
public abstract class OpelAuto extends F ...
public abstract class MercedesAuto extends F ...
public Manta extends OpelAuto ...
public abstract class W ...
public class OpelWerkstatt extends W ...
public class MercedesWerkstatt extends W ...
Nun hat die abstrakte Klasse W eine abstrakte Methode
repariere(F fahrzeug). Der Fzg.besitzer kann also auf die vom Guru
erhaltene, von W abgeleitete Instanz einfach repariere(meinAuto)
aufrufen, egal welches konkrete Auto er hat und egal, welche konkrete
Werkstatt er vom Guru erhalten hat.
Jetzt kommt's:
Damit einer Opelwerkstatt auch nur Opelfahrzeuge zur Reparatur in
Auftrag gegeben werden, wollte ich die repariere-Methode dort so
implementieren:
public class OpelWerkstatt extends W ...
repariere(OpelAuto o)
Da meckert der Compiler natürlich, dass OpelWerkstatt doch bitte
repariere(F) implementieren möge.
Logisch, OpelWerkstatt ist eine W(erkstatt) und die kann nach Definition
Fahrzeuge reparieren, nicht nur Opels.
Lösung a)
Ich implementiere die allgemeinere Methode repariere(F) und prüfe zur
Laufzeit (explizit per instanceof oder implizit per casten) auf den Typ
OpelAuto
public class OpelWerkstatt extends W ...
repariere(F fahrzeug)
if (! fahrzeug instanceof OpelAuto)
throw new UngueltigeFahrzeugMarke()
Solche Typüberprüfungen zur Laufzeit finde ich aber unschön.
Gibt's da auch was besseres?
TIA
Bye
Achim
ich bin nach ein paar Jahren verhaltener Pause wieder massiv beim OO (in
Java) aber OO-design-technisch etwas aus der Übung, und da hab' ein gern
emal ein Problem(chen), was in einer Compile-Fehlermeldung endet.
Die Meldung ist mir klar, ich weiß, warum sie kommen muß, und ich weiß,
wie ich sie umgehe. Ich möchte sie aber _elegant_ wegbekommen, und sei
es, dass ich dafür ein anderes Klassen-Design wählen muss. Da es somit
eine Designfrage ist, wähle ich ein beispielhaftes, leichter
darzustellendes Problem, das m. E. die konkreten Abhängigkeiten
hinreichend widerspiegelt.
Es gibt Fahrzeuge F, die manchmal repariert werden müssen, und
spezialisierte Reparatur-Werkstätten W pro Fahrzeughersteller. Wer eine
Reparatur in Auftrag geben will, hat ein konkretes Fahrzeug an der Hand,
er weiß aber nicht, welcher Reparatur-Firmen-Typ zuständig ist (eine
Mercedes-Werkstatt für einen 500SL und A-Klasse, Opel für Manta und
Vectra, etc.) Das ist aber rauszubekommen (z. B. weiß das ein Guru).
Jedefalls erhält der Fzg-Besitzer eine Instanz einer von W abgeleiteten
Klasse und die möchte er gerne mit repariere(meinAuto) aufrufen.
Die Klasse W habe ich jetzt als abstrakte Oberklasse aller
Reparaturwerkstättentypen definiert (weil der Guru einfach eine
zuständige "Werkstatt" liefert) und die Klasse F als abstrakte
Oberklasse aller Fahrzeugmarken definiert (weil eine Werkstatt allgemein
ein "F(ahrzeug)" repariert, Z. B.
public abstract class F ...
public abstract class OpelAuto extends F ...
public abstract class MercedesAuto extends F ...
public Manta extends OpelAuto ...
public abstract class W ...
public class OpelWerkstatt extends W ...
public class MercedesWerkstatt extends W ...
Nun hat die abstrakte Klasse W eine abstrakte Methode
repariere(F fahrzeug). Der Fzg.besitzer kann also auf die vom Guru
erhaltene, von W abgeleitete Instanz einfach repariere(meinAuto)
aufrufen, egal welches konkrete Auto er hat und egal, welche konkrete
Werkstatt er vom Guru erhalten hat.
Jetzt kommt's:
Damit einer Opelwerkstatt auch nur Opelfahrzeuge zur Reparatur in
Auftrag gegeben werden, wollte ich die repariere-Methode dort so
implementieren:
public class OpelWerkstatt extends W ...
repariere(OpelAuto o)
Da meckert der Compiler natürlich, dass OpelWerkstatt doch bitte
repariere(F) implementieren möge.
Logisch, OpelWerkstatt ist eine W(erkstatt) und die kann nach Definition
Fahrzeuge reparieren, nicht nur Opels.
Lösung a)
Ich implementiere die allgemeinere Methode repariere(F) und prüfe zur
Laufzeit (explizit per instanceof oder implizit per casten) auf den Typ
OpelAuto
public class OpelWerkstatt extends W ...
repariere(F fahrzeug)
if (! fahrzeug instanceof OpelAuto)
throw new UngueltigeFahrzeugMarke()
Solche Typüberprüfungen zur Laufzeit finde ich aber unschön.
Gibt's da auch was besseres?
TIA
Bye
Achim