Hallo geschätzte Mit-Delphianer!
Mir stellt sich soeben folgendes Problem:
Ich habe in meiner Parserklasse eine Prozedur, die das Zerlegen eines Strings vornimmt. Nun kann mein Parser mit reellen Zahlen, komplexen, und Quaternionen rechnen. Um ihm mitzuteilen, welchen Zahlentyp man nun benutzen möchte, muss eine entsprechende Property gesetzt werden.
Der String-Zerleger baut die resultierende Formel in einen Baum um - und die Knoten (eigene Klassen) sind nun vom verwendeten Zahlenformat abhängig.
D.h.:
Code:
reelle Zahlen : Knoten sind der Klasse T[b]R[/b]Node
komplexe Zahlen: Knoten sind der Klasse T[b]C[/b]Node
Quaternionen : Knoten sind der Klasse T[b]Q[/b]Node
Also habe ich derzeit gleich DREI Prozeduren die, je nach Zahlenformat, in einen entsprechenden Baum parsen. Und da diese Prozeduren
sehr ähnlich sind, und zu dem recht lang, fände ich es jetzt eleganter daraus EINE zu machen.
Sie sind wie folgt deklariert:
procedure TCQParser.TTR(s: string; var currentND: TQNode);
s ist der zu parsende String, und currentND ist der Kandidat um den es geht. Er ist in diesem Bsp. vom Typ TQNode, es handelt sich also um die Prozedur die den Baum für eine Formel mit Quaternionen aufbaut. Es gibt die gleichen Deklarationen noch 2 mal, nur mit dem Unterschied, dass "currentND" anderen Typs ist.
IN der Prozedur ändert sich eigentlich nur folgendes:
Delphi-Quellcode:
// ein:
currentND := TQNode.Create(addQ);
// wird bei der Version mit Quaternionen geschrieben, aber
currentND := TCNode.Create(addC);
// bei der Version mit komplexen Zahlen, und
currentND := TRNode.Create(opAdd);
// bei reellen Zahlen
Die Parameter die im Create übergeben werden sind in den ersten beiden Fällen Pointer auf eine Function, und im dritten Fall ein Set-Element.
Die Frage ist also, ob ich "currentND" irgendwie sinnvoll SO angeben kann, so dass ich im Rumpf dann komfortabel auf den EIGENTLICHEN Typ reagieren kann. Komfortabel deswegen, weil diese "currentND := ..."-Zeilen ca. 25-30 mal in der Prozedur auftauchen, und es soll noch mehr werden
Einen untypisierten Pointer würde ich zu gerne vermeiden, da ich möglichts D8-Kompatibel arbeiten möchte. (Ich hab D8 zwar nicht, aber ich meine gelesen zu haben, dass untyp. Pointer dort nicht drin sind...)
Im gleichen Zuge ist das Problem vorhanden, dass ich dem Parser die Möglichkeit eingeräumt habe 8 Variablen zu unterstützen, deren Änderung ohne neues Parsen wirken. Dazu habe ich bei der Deklaration der Klasse 8 public-Variablen. Nun können die aber 3 verschiedene Typen haben: TQuat, TComplex oder double.
Also habe ich 3x8 Variablen:
Ar, Br, Cr, ... für reelle Zahlen
Ac, Bc,
Cc, ... für komplexe Zahlen und so weiter.
Ich würde aber viel lieber einfach A, B, C, ... einrichten, und der Typ soll sich nach dem vorbestimmten Nummernformat richten.
So sieht's z.Zt. aus:
Delphi-Quellcode:
TNumFormat = (nfReal, nfComplex, nfQuaternion);
TCQParser =
class(TObject)
private
rootR: TRNode;
rootC: TCNode;
rootQ: TQNode;
procedure FlushTrees;
procedure TTR(s:
string;
var currentND: TRNode);
overload;
procedure TTR(s:
string;
var currentND: TCNode);
overload;
procedure TTR(s:
string;
var currentND: TQNode);
overload;
public
// grausig hier... :)
Ar, Br, Cr, Dr, Er, Fr, Gr, Hr: double;
Ac, Bc,
Cc,
Dc,
Ec, Fc, Gc, Hc: TComplex;
Aq, Bq, Cq, Dq, Eq, Fq, Gq, Hq: TQuat;
NumberFormat: TNumFormat;
procedure Parse(s:
string);
procedure Solve(
var res: double);
overload;
procedure Solve(
var res: TComplex);
overload;
procedure Solve(
var res: TQuat);
overload;
constructor Create;
destructor Destroy;
override;
end;
Ich habe das jetzt mal zusammen in diesen Thread gepackt, da ich
schätze, dass das artverwandte Probleme sind. Falls das Murks war sagt nur fix bescheid - dann teile ich das gerne auf
Danke euch schonmal brühwarm,
dizzy
Fabian K.
INSERT INTO HandVonFreundin SELECT * FROM Himmel