![]() |
Re: Mal wieder Klassenvererbung
Hallo,
das mit TPersistent als Vorfahre würde so funktionieren, allerdings will ich mein Objekt nicht dermaß aufbauschen, da ich bis zu mehreren hundert Instanzen erzeugen muss. Mit TPersistent würde das nur unnötig den Speicher vollschreiben. Gruß, Tom |
Re: Mal wieder Klassenvererbung
Moin!
Schonmal meinen Vorschlag überdacht bzw. den probiert? MfG Muetze1 |
Re: Mal wieder Klassenvererbung
Zitat:
was genau verstehst du unter einer Metaklasse... So wie du es beschreibst soll ich über Classname auf die Klasse zugreifen... Ist es da aber nicht so, daß ich mindestens von TPersistent ableiten muß? Gruß, Tom |
Re: Mal wieder Klassenvererbung
Moin!
Delphi-Quellcode:
So, da hast du dann deine Basisklasse mit dem Constructor und einer Funktion die dir die ID für das Objekt gibt als String. Dies kann dann z.B. "Kreis" oder "Quadrat" sein. Diese Funktion kann als Class Funktion auch ohne eine Instanz aufgerufen werden. Darüber können wir dann später die richtige Klasse finden - wenn in deiner Textdatei denn drinne steht "Kreis" (z.B.).
Unit Geometrie;
Interface Type TGeometrieMetaClass = Class Of TGeometrie; // das ist die Metaklasse TGeometrie = Class Public Constructor Create; Virtual; Destructor Destroy; Override; Class Function ObjektID: String; Virtual; Abstract; End; Ok, nun brauchen wir nur noch eine Funktionalität, die die ganzen Typen annimmt und sie alle kennt:
Delphi-Quellcode:
So, dann bekommst du mit GetMetaClassForID() schon die fertig angelegte Instanz der Klasse zurück die du suchst. Du musst nun nur noch 2 Dinge machen:
Unit GeometrieRegSvr;
Interface Uses Geometrie; Function GetMetaClassForID(Const AID: String): TGeometrie; Procedure RegisterGeometrieClass(AClass : TGeometrieMetaClass); Implementation Var GeometrieClasses : Array Of TGeometrieMetaClass; Procedure RegisterGeometrieClass(AClass : TGeometrieMetaClass); Var i : Integer; Begin // already registered? For i := Low(GeometrieClasses ) To High(GeometrieClasses ) Do If ( GeometrieClasses [i] = AClass ) Then Exit; SetLength(GeometrieClasses , Length(GeometrieClasses )+1); GeometrieClasses [Length(GeometrieClasses )-1] := AClass ; End; Function GetMetaClassForID(Const AID: String): TGeometrie; Var i : Integer; Begin For i := Low(GeometrieClasses) To High(GeometrieClasses) Do If ( UpperCase(GeometrieClasses[i].ObjektID) = AID) Then Begin Result := GeometrieClasses[i].Create; Exit; End; Raise Exception.Create('unbekannter Geometrietyp ' + AID + '!'); End; 1. Alle deine TKreis, TQuadrat oder sonstige von TGeometrie ableiten und die ObjektID Procedure überschreiben und diese Kennung jeweils zurück geben. Diese Kennung ist gleich der die in die Datei geschrieben wird und gleich der die aus der Datei gelesen wird und die Klasse identifiziert. 2. In diesen Units die dann jeweils ein Objekt enthalten (also z.B: TKreis) musst du einmal diese Klasse hier registrieren. Dies machst du am besten im Initialize der Unit:
Delphi-Quellcode:
Und dann klappt das auch schon.
Initialization
// registering the string adapter to the converter RegisterGeometrieClass(TKreis); end. MfG Muetze1 |
Re: Mal wieder Klassenvererbung
Das ganze ist eigentlich ganz einfach. Du musst nur beim erstellen des Objectes prüfen von welchem Typ es ist und den entpsrechenden Konstructor des Nachfahren aufrufen. Anschließend kannst du über die gemeinsame Methode drauf zugreifen ohne dir gedanken drüber machen zu müssen ob es ein Quader oder eine Kugel ist.
Delphi-Quellcode:
type
TGeometrie = class public function VolumenBerechnen: Extended; virtual; abstract; end; TKugel = class(TGeometrie) public function VolumenBerechnen: Extended; override; end; TQuader = class(TGeometrie) public function VolumenBerechnen: Extended; override; end; [...] function TKugel.VolumenBerechnen: Extended; begin result := //Volumen für Kugel berechnen end; function TQuader.VolumenBerechnen: Extended; begin result := //Volumen für Quader berechnen; end; ///uns so geht man dann damit um procedure Irgendwas; var LObj: TGeometrie; begin if ZeileAusDatei = Quader then //Hier entscheidet sich von welchem Typ das Object wird LObj := TQuader.Create else Lobj := TKugel.Create; //und dann einfach die gemeinsame Methode aufrufen showMessage(FloatToStr(LObj.VolumenBerechnen)); end; |
Re: Mal wieder Klassenvererbung
Moin!
Zitat:
MfG Muetze1 |
Re: Mal wieder Klassenvererbung
Hallo Muetzel1,
ich hab jetzt mal versucht deinen Code zu testen, und es klappt auch soweit.
Delphi-Quellcode:
probier ich dann meine Klassen zu erzeugen... In der GetMetaClassForID Funktion krieg ich dann aber einen abstrakten Fehler als Rückmeldung, wenn dort versucht wird auf GeometrieClasses[i].ObjektID zuzugreifen.
var
Geometrien : array of TGeometrie ; ... Setlength(Geometrien,2) ; Geometrien[0] := GetMetaClassForID ('QUADER').Create ; Geometrien[1] := GetMetaClassForID ('KUGEL').Create ; Ich hab womöglich noch einen Fehler drin, wahrscheinlich in der Überschreibung der ClassID Methoden... So siehts bei mir aus:
Delphi-Quellcode:
Oder ich hab alles durcheinander geworfen...
TKugel = class (TGeometrie)
public class Function ObjectID : string ; end ; ... class function TKugel.ObjectID: string; begin Result := 'KUGEL' ; end; Aber Hut ab, wenn ich das am Laufen hab, ist es genau das was ich gesucht habe :firejump: Ech cool. Gruß, Tom |
Re: Mal wieder Klassenvererbung
Moin!
Jo, 2 Dinge noch dazu: 1.
Delphi-Quellcode:
Da brauchst du kein Create mehr, die GetMetaClassForID() macht das schon intern und gibt dir schon das Ergebnis von dem Constructor-Aufruf zurück. Also du bekommst mit jedem Aufruf von GetMetaClassForID() eine ordentliche neue Instanz geliefert.
Geometrien[0] := GetMetaClassForID ('QUADER').Create ;
Geometrien[1] := GetMetaClassForID ('KUGEL').Create ; 2. Ja, bei der abstrakten Methode ist das soweit ok, du musst nur noch oben in der Klasse ein Override hinten mit angeben:
Delphi-Quellcode:
Und dann sollte das klappen!
TKugel = class (TGeometrie)
public class Function ObjectID : string; Override; end ; ... class function TKugel.ObjectID: string; begin Result := 'KUGEL' ; end; Ach ja: du gibst ja jetzt noch das "Kugel" und "Quadrat" direkt an - aber später liest du die Strings doch aus der Textdatei, oder? Weil so hatte ich es mir ja gedacht, dann brauchst du später auch nicht mehr angeben, das du jetzt eine Kugel brauchst sondern du liest einfach nur den Typ aus der Datei... Ansonsten solltest du vielleicht noch eine Fehlerbehandlung mit einbauen, weil wenn du ihm einen unbekannten Typstring übergibst (also einen String wozu keine Klasse registriert ist), dann bekommst du eine Exception. Diese solltest du abfangen und dem entsprechend reagieren. Und nochwas: wenn du in der GetMetaClassForID Funktion die AID mit einem UpperCase() umschliesst, dann kannst du auch ruhig "Kugel" oder so schreiben und musst somit nicht mehr auf Gross- und Kleinschreibung achten. Auch die Klassen können bei ObjektID dat ganze klein geschrieben - oder halt normal geschrieben zurück geben. MfG Muetze1 |
Re: Mal wieder Klassenvererbung
Ups, Nachtrag,
Hab mal wieder zu fix gehackt... Hatte in TGeometrie ObjektID definiert, und in TKreis, TQuader jedoch ObjectID... Also kein Wunder, daß da ein abstrakter Fehler kommt. Jetzt klappts, helau... Besten Dank für die Mühe. Gruß, Tom |
Re: Mal wieder Klassenvererbung
Zitat:
Gruß, Tom |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:58 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz