In Kindklassen anderer Memberdatentyp
-
Servus,
mein Problem lässt sich am besten durch ein kleines Beispiel darstellen:
class Auto { private Fahrer autofahrer; public Fahrer Autofahrer { get return autofahrer; } } class Ferrari : Auto { private FerrariFahrer autofahrer; public Ferrarifahrer Autofahrer { get return autofahrer; } }
Die Klasse "Ferrari-Fahrer" leitet sich von der Klasse "Fahrer" ab!
Meine Frage ist, ob es möglich ist, in abgeleiteten Klassen einen Memberdatentyp in einen davon abgeleiteten Typ zu verändern...hier von "Fahrer" zu "FerrariFahrer"?
Merci für die Antworten...
Servus
-
Nutz doch den Polymorphismus. Du kannst doch im Konstruktor von Ferrari ein Ferrarifahrer-Objekt dem protected Fahrer zuweisen. Oder gibt es spezielle Ferrarifahrer-Eigenschaften die Du nicht kapseln willst und die Ferrari kennen muß?
-
witte schrieb:
Oder gibt es spezielle Ferrarifahrer-Eigenschaften die Du nicht kapseln willst und die Ferrari kennen muß?
Nein, gibt es eigentlich nicht! Deine Methode hatte ich auch schon im Kopf, aber es wäre ja dann theoretisch möglich, dem Fahrer-Member von Ferrari ein AudiFahrer-Objekt zuzuweisen! Deswegen hätte ich es gern so "typsicher" wie es nur geht :-)!
Aber danke für die Antwort, ist auf jeden Fall ein guter Ansatz!
-
Design-Fanatic schrieb:
Deswegen hätte ich es gern so "typsicher" wie es nur geht :-)!
Dann mußt Du Dir im Klaren sein was Du unter Typsicherheit meinst bzw. was Du erreichen willst. Du musst Dir die Frage beantworten können 'Was ist so schlimm daran dass ein Audi-Fahrer den Ferrari benutzen kann?' Man könnte beispielsweise den Fahrertypen Schnittstellen implementieren lassen und nur Fahrer akzeptieren die notwendge Schnittstellen implementiert haben.
-
Geht denn der obige Code nicht? Ich bin mir gerade nicht sicher und habe auch kein .NET dabei aber ich habe vage in Erinnerung, dass C# kovariante Methodenüberschreibung erlaubt, und genau das ist bei Dir der Fall. Die Membervariable überschreibst Du dann natürlich nicht sondern rufst einfach `base.Autofahrer` auf.
Ansonsten: Deine Properties sind doch eh read-only, daher ist die Typensicherheit nicht beeinträchtigt. Du kannst im Konstruktor ja nach wie vor ein `FerrariFahrer`-Objekt übergeben.
Und noch was: *wenn* die Properties read-only sind, dann mach doch auch die Membervariable read-only:
class Auto { private readonly Fahrer autofahrer; public Auto(Fahrer autofahrer) { this.autofahrer = autofahrer; } public Fahrer Autofahrer { get { return autofahrer; } } } class Ferrari : Auto { public Ferrari(Ferrarifahrer autofahrer) : base(autofahrer) { } public Ferrarifahrer Autofahrer { get { return base.Autofahrer; } } }
-
public Ferrarifahrer Autofahrer { get { return base.Autofahrer; } }
Bist du dir sicher, dass das geht? Ich bin mir grad nicht sicher, ob er das implizit wieder zu einem FerrariFahrer-Objekt castet?! Aber is nen interessantes Thema!
Wenn ich dich richtig verstanden habe, benutzt du die Membervariable als "Holder", um sie in abgeleiteten Klassen je nach Objektdatentyp casten zu lassen (vorausgesetzt obiges funktioniert!).Wäre es auch möglich, die Membervariable als "protected" zu deklarieren, dann bräuchte ich ja nicht mal mit "base.Autofahrer" auf das Property der Basisklasse zugreifen, sondern könnte einfach "this.autofahrer" schreiben?!
Grüße
-
Design-Fanatic schrieb:
public Ferrarifahrer Autofahrer { get { return base.Autofahrer; } }
Bist du dir sicher, dass das geht?
Wie gesagt: ich bin mir nicht ganz sicher. Probier's halt aus.
Ich bin mir grad nicht sicher, ob er das implizit wieder zu einem FerrariFahrer-Objekt castet?!
Hehe, da hast Du natürlich recht: ein Cast gehört da noch hin. Der ist dafür aber sicher, weil wir ja wissen, dass wir das Objekt als Ferrarifahrer initialisiert haben. Also folgendermaßen:
public Ferrarifahrer Autofahrer { get { return (Ferrarifahrer)base.Autofahrer; } }
Wäre es auch möglich, die Membervariable als "protected" zu deklarieren, dann bräuchte ich ja nicht mal mit "base.Autofahrer" auf das Property der Basisklasse zugreifen, sondern könnte einfach "this.autofahrer" schreiben?!
Möglich wäre es, das hätte aber keinen Vorteil und jede Menge Nachteile. Grundsätzlich gilt: Membervariablen *immer* `private`, ohne Ausnahme. Eine Diskussion dazu gibt's auf Stack Overflow. Zusätzlich zur Erklärung: wenn Du es mal ändern musst, weil sich das Verhalten ändert, dann geht die Binärkompatibilität kaputt und es müssen alle Anwendungen neu kompiliert werden, die Deine Assembly verwenden. Das ist zwar nur relevant, wenn man eine DLL programmiert, aber man sollte es als generellen Grundsatz einfach übernehmen, da es keine Nachteile hat, sich überall daran zu halten.
-
Ok verstehe... das mit der Binärkompatibilität leuchtet mir ein!
Aber ist es eigentlich nicht unsauber mitpublic Ferrarifahrer Autofahrer { get { return (Ferrarifahrer)base.Autofahrer; } }
mit dem Property "von außen" auf die Vaterklasse zuzugreifen, obwohl ich ja eigentlich schon "im" Objekt bin und die Objektvariable erben könnte?! Deswegen die Frage mit der "Protected"-Deklaration. Aber wenn ich so drüber nachdenke, ist mir die Binärkompatibilität doch wichtiger als so ne Lappalie :-)!
Danke für die Antwort!
Grüße
-
Design-Fanatic schrieb:
Ok verstehe... das mit der Binärkompatibilität leuchtet mir ein!
Aber ist es eigentlich nicht unsauber mitpublic Ferrarifahrer Autofahrer { get { return (Ferrarifahrer)base.Autofahrer; } }
mit dem Property "von außen" auf die Vaterklasse zuzugreifen, obwohl ich ja eigentlich schon "im" Objekt bin und die Objektvariable erben könnte?!
Ne, das ist nicht unsauber.
Eher im Gegenteil …