Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Variablen Unitübergreifend übergeben
mexx - Mo 29.01.07 16:53
Titel: Variablen Unitübergreifend übergeben
Ich rufe aus einer Unit eine Function aus. Diese Function liefert mir per Result ein Ergebnis zurück. Nun möchte ich aber mehr als nur ein Ergebnis erhalten. Ich könnte in der Unit2, wo sich die aufgerufene Function befindet weitere Variablen definieren und mit Werten belegen, aber wie kann ich diese Variablen in der Unit1 benutzen. Ich bin mir sicher, dass es geht und dass es einfach ist, aber ich weis nicht wie.
Ein Beispiel:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| Unit1 ... uses Unit2 ... erg := function math(1,1); Showmessage(VarFuerUnit1); |
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| Unit2 ... uses Unit1 ... function math(zahl1,zahl2:integer):Integer; begin result := zahl1 + zahl2; VarFuerUnit1 := 'Hallo Welt'; end; |
Welches ist der sauberste und richtige Weg?
wdbee - Mo 29.01.07 17:08
Da gibt es je nach Einsatzzweck eine ganz Reihe von "richtigen" Lösungen.
Was aber generell möglich ist, egal ob du mit Klassen arbeiten willst oder nicht, ist der Einsatz einer Unit "Global" , in der du alle globalen Vereinbarungen im Interface-Abschnitt unterbringst (Type, Konstanten, Variablen usw.). Alle deine eigentlichen Units können die in der uses Klausel des eigenen Interfaces haben und so auch im Interface alles verwenden, ohne das es jemals Kreuzbezüge geben kann.
Im Quellcode schreibst du dann statt Variablenname einfach Global.Variablenname und das war es schon.
mexx - Mo 29.01.07 17:11
Demnach müsste es gehen, wenn ich globale Variablen in der Unit2 definiere. Dann müsste ich sie in der Unit1 benutzen können?
mexx - Mo 29.01.07 17:18
Thx! Da ja bekanntlich mehrere Wege nach Rom führen, hätte ich gedacht, es gibt eine Methode dafür, die von den Profis bevorzugt verwendet wird.
wdbee - Mo 29.01.07 17:32
Mag sein dass das bei dir geht, aber generell können dann Probleme auftreten, wenn du überkreuzende Bezüge zwischen deinen Units bekommst.
jaenicke - Mo 29.01.07 18:22
Wie wärs so:
Delphi-Quelltext
1: 2: 3: 4: 5:
| function Division(zahl1, zahl2: Integer; var Rest: Integer): Integer; begin Result := zahl1 div zahl2; Rest := zahl1 mod zahl2; end; |
mexx - Di 30.01.07 09:19
jaenicke hat folgendes geschrieben: |
Wie wärs so:
Delphi-Quelltext 1: 2: 3: 4: 5:
| function Division(zahl1, zahl2: Integer; var Rest: Integer): Integer; begin Result := zahl1 div zahl2; Rest := zahl1 mod zahl2; end; | |
Wie kann ich var Rest verstehen? Als Eingabeparameter beim Aufruf der funktion oder als Ergebnismenge der Funktion?
Kroko - Di 30.01.07 10:20
nein, als Rückgabeparameter
daher würde ich den Kopf wie folgt abändern:
Delphi-Quelltext
1: 2: 3: 4: 5:
| function Division(const zahl1, zahl2: Integer; out Rest: Integer): Integer; begin Result := zahl1 div zahl2; Rest := zahl1 mod zahl2; end; |
mexx - Mi 31.01.07 10:05
Rufe ich aber nun die Function auf, so erwartet er von mir einen weiteren Parameter Rest. Ich will den Parameter aber nicht beim Aufruf eingeben, sondern als weiteres Ergebnis erhalten.
nivosta - Mi 31.01.07 10:26
Guten morgen,
ich glaube der richtige Weg in diesem Fall ist wenn man eine Result Record strucktur deklariert und diese zurückgibt, ist auch Programmiertechnisch die sauberste Lösung
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| type TMeinResult = packed record var1 : string; var2 : integer; end;
. . .
function tuWas() : TMeinResult; begin result.var1 := 'Test'; result.var2 := 12; end: |
jaenicke - Mi 31.01.07 10:37
mexx hat folgendes geschrieben: |
Rufe ich aber nun die Function auf, so erwartet er von mir einen weiteren Parameter Rest. Ich will den Parameter aber nicht beim Aufruf eingeben, sondern als weiteres Ergebnis erhalten. |
Genau das ist doch auch, was passiert!
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| function Division(const zahl1, zahl2: Integer; out Rest: Integer): Integer; begin Result := zahl1 div zahl2; Rest := zahl1 mod zahl2; end;
var rest: Integer; begin ShowMessage('12 durch 5 ist ' + IntToStr(Division(12, 5, rest)) + ', Rest ' + IntToStr(rest)); end; |
nivosta hat folgendes geschrieben: |
ich glaube der richtige Weg in diesem Fall ist wenn man eine Result Record strucktur deklariert und diese zurückgibt, ist auch Programmiertechnisch die sauberste Lösung |
Ob das nun die sauberste Lösung ist, da kann man sich drüber streiten. Out existiert ja nicht ohne Grund und manchmal möchte ich nicht mit Records arbeiten, aber das ist Geschmackssache.
Es ist jedenfalls eine weitere Lösung, die natürlich auch gut funktioniert.
mexx - Mi 31.01.07 13:06
Ich finde die Lösung aber ganz gut. Bei mir stimmt nur was nicht. Schaut mal bitte.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| ... public end;
type TSaveResults = Record SSaveToFile, SSaveToTemplate: Boolean; SFileName, SSaveName: String; end;
function ReportSaveDialog(ADataSet: TDataSet): TSaveResults;
var FstReportDlg: TFstReportDlg;
implementation {$R *.dfm} ... function ReportSaveDialog(ADataSet: TDataSet): TSaveResults; begin ... SSaveToFile := true; ... end; |
[Fehler] FastRptDialg.pas(176): Undefinierter Bezeichner: 'SSaveToFile'
Woran liegts? Falsche Definietion des Records?
jaenicke - Mi 31.01.07 13:07
Es fehlt das Result. davor, denn das ist ja schließlich in dem Ergebnis-Record drin.
mexx - Mi 31.01.07 13:57
Aha! Das eigentliche Problem war aber, dass ich diese Ergebnisse, die nun in meinen Record stehen, auch in einer anderen Unit sehe. Dort ist aber derRecord, so wie der Quelltext jetzt ist, nicht zu sehen.
jaenicke - Mi 31.01.07 13:59
Dann erstelle eine neue Unit, pack dort die Record-Definition rein, und binde diese Unit via uses in alle Units ein, die den benutzen.
mexx - Mi 31.01.07 14:02
Der Aufruf der Werte geschieht über
Delphi-Quelltext
1:
| ReportSaveDialog(Query).SSaveName |
zum Beispiel. Aber rufe ich da nicht jedesmal die Funktion auf, wenn ich die Var SSaveName oder die anderen Records verwenden will?
jaenicke - Mi 31.01.07 14:04
Du solltest den Rückgabewert zunächst in eine Variable vom Typ des Records speichern ;-).
Kroko - Mi 31.01.07 14:05
mexx hat folgendes geschrieben: |
Rufe ich aber nun die Function auf, so erwartet er von mir einen weiteren Parameter Rest. Ich will den Parameter aber nicht beim Aufruf eingeben, sondern als weiteres Ergebnis erhalten. |
(a)Die Proc erwartet keinen weiteren Parameter sondern eine Variable, die zurück gegeben werden soll!
PS: Gilt hier nicht mehr, neue Frage neuer Thread :?:
jaenicke - Mi 31.01.07 14:06
Kroko hat folgendes geschrieben: |
PS: Gilt hier nicht mehr, neue Frage neuer Thread :?: |
Ist doch immer noch dasselbe Problem... :gruebel:
mexx - Mi 31.01.07 14:07
jaenicke hat folgendes geschrieben: |
Du solltest den Rückgabewert zunächst in eine Variable vom Typ des Records speichern ;-). |
Dann erachte ich diese Lösung als eher unangenehm und nicht so praktisch.
Kroko - Mi 31.01.07 15:07
jaenicke hat folgendes geschrieben: |
Kroko hat folgendes geschrieben: | PS: Gilt hier nicht mehr, neue Frage neuer Thread :?: |
Ist doch immer noch dasselbe Problem... :gruebel: |
:gruebel: function Division...
:gruebel: =ReportSaveDialog(Query).SSaveName
:gruebel:
:wink:
jaenicke - Mi 31.01.07 19:13
Kroko hat folgendes geschrieben: |
jaenicke hat folgendes geschrieben: | Kroko hat folgendes geschrieben: | PS: Gilt hier nicht mehr, neue Frage neuer Thread :?: |
Ist doch immer noch dasselbe Problem... :gruebel: |
:gruebel: function Division...
:gruebel: =ReportSaveDialog(Query).SSaveName
:gruebel: |
:lol: Meine Funktion Division war doch nur ein Beispiel, danach war doch gar nicht gefragt! Dass die Funktion nun ReportSaveDialog heißt, um die es geht, ist doch egal...
mexx hat folgendes geschrieben: |
jaenicke hat folgendes geschrieben: | Du solltest den Rückgabewert zunächst in eine Variable vom Typ des Records speichern ;-). |
Dann erachte ich diese Lösung als eher unangenehm und nicht so praktisch. |
Ähm, wie willst du denn mit zwei Rückgabewerten gleichzeitig arbeiten ohne zumindest einen davon zwischenzuspeichern??? :gruebel:
Und an meinem Beispiel siehst du, wie du innerhalb einer "Abfrage" mit dem zweiten Ergebnis gleich weiterarbeiten kannst (dann mit dem übergebenen Speicherort für den zweiten Rückgabewert als out-Parameter).
Ohne eine Variable UND ohne einen Neuaufruf der Funktion ist es IMHO vollkommen unmöglich! Und zwar nicht nur in Delphi...
Wenn du ohne Variable auskommen musst/willst, dann ist dein Konzept ähh... sagen wir... IMHO nicht sinnvoll.
Ich sehe auch keinen Grund, warum man das irgendwo ohne Variable machen müsste. Wirklich! Das meine ich ernst! Ich sehe keinen Fall, wo das nur ohne Variable ginge/sinnvoll wäre....
Wenn das bei dir nicht geht, dann solltest du vielleicht mal sagen, warum. Vor allem, weil du doch sogar globale Variablen als Möglichkeit in Betracht gezogen hast.
Mit denen kannst du es durchaus machen. Würde ich zwar nicht so machen, aber es geht damit.
BTW: Wenn du die Windows API verwendest, dann kommst du um Variablen als Parameter, in die der Rückgabewert reinkommt, nicht herum. (Ob man die API jetzt in Zeiten der OOP als Beispiel nehmen sollte, sei mal dahingestellt... ;-))
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!