Autor |
Beitrag |
Flamefire
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: Di 22.02.11 01:05
Ich möchte ein Objekt als Referenzparamter übergeben.
Meine Funktion sieht so aus:
Delphi-Quelltext 1:
| procedure RegisterMerge(var aWhat:TMergeable); overload; |
TMergeable ist genau die Klasse, in der diese Funktion definiert wird und wird von TObject abgeleitet.
Jetzt habe ich eine Klasse, die 2 mal von dieser abgeleitet wurde.
Bsp:
Delphi-Quelltext 1: 2:
| TFoo=class(TMergeable); TBar=class(TFoo); |
Wenn ich jetzt RegisterMerge mit einer Instanz von TBar aufrufen will, sagt der Compiler mir, dass ich die nicht mit diesen Argumenten aufrufen kann.
Definiere ich die Funktion so:
Delphi-Quelltext 1:
| procedure RegisterMerge(var aWhat:PMergeable); overload; |
und rufe die mit RegisterMerhe(@Bar) auf ist alles ok. Aber ist unschön mit dem @
Was läuft da schief? Errorinsight meckert (ausnahmsweise) mal nicht...
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Di 22.02.11 01:23
Flamefire hat folgendes geschrieben : | Wenn ich jetzt RegisterMerge mit einer Instanz von TBar aufrufen will, sagt der Compiler mir, dass ich die nicht mit diesen Argumenten aufrufen kann. |
Und das aus gutem Grund. Denn sonst könnte die Methode in eine TBar-Variable ein TMergeable-Objekt stecken, was man wohl lieber vermeiden sollte  .
_________________ >λ=
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Di 22.02.11 02:04
Kha hat folgendes geschrieben : | Und das aus gutem Grund. Denn sonst könnte die Methode in eine TBar-Variable ein TMergeable-Objekt stecken, was man wohl lieber vermeiden sollte . |
Stimmt, aber er probiert ja genau das Gegenteil: TBar-Objekt in TMergeable-Variable.
Es müsste funktionieren, wäre der Parameter nicht ein Var-Parameter. Ich vermute mal, hier schlägt sich das Klassenmodell mit der Regel dass Variablenparameter immer genau vom Typ des Parameters sein müssen.
Wird sich wohl nicht ändern lassen.... 
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
Tranx
      
Beiträge: 648
Erhaltene Danke: 85
WIN 2000, WIN XP
D5 Prof
|
Verfasst: Di 22.02.11 05:11
Genau, bei nicht VAR-Parametern funktioniert das. Aber warum unbedingt ein VAR-Parameter? Welchen Nutzen hätte das? Ich will doch nicht den Typ ändern, ich will in der Regel doch bloß die Typ-Methoden und Eigenschaften nutzen, oder sehe iuchg das falsch?
Zumal, ich hoffe ich liege da nicht verkehrt, ist die Übergabe einem Typ als Parameter so etwas wie die Übergabe eines Zeigers auf den Typ. Ich greife also auf den Typ selber zu. Und somit kann ich auch alle öffentlich deklarierten Methoden/Eigenschaften nutzen und Variablen ändern, und zwar dauerhaft.
_________________ Toleranz ist eine Grundvoraussetzung für das Leben.
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 22.02.11 07:51
Richtig, hier ist ein Assign vermutlich sinnvoller, wenn nur Daten befüllt werden sollen. Denn wenn RegisterMerge eine Factory-Funktionalität haben soll, dann sollte der Wert als Rückgabewert definiert werden und die Funktion entsprechend heißen.
Denn was passiert sonst mit dem alten Objekt (denn es ist ja ein var- und kein out-Parameter)? Wird es darin auch freigegeben? Ist es anderweitig noch gespeichert? Alles nicht so ganz sauber.
Flamefire hat folgendes geschrieben : | Definiere ich die Funktion so:
Delphi-Quelltext 1:
| procedure RegisterMerge(var aWhat:PMergeable); overload; |
und rufe die mit RegisterMerhe(@Bar) auf ist alles ok. Aber ist unschön mit dem @ |
Das finde ich noch nicht einmal. Denn dadurch sieht man zumindest, dass das Objekt neu zugewiesen werden könnte. Am Namen der Prozedur lässt sich das ja nicht wirklich erkennen...
Schreib doch einfach einmal den Hintergrund zu dem Quelltext, also du damit eigentlich machen möchtest.  Dann hat jemand vielleicht eine bessere Umsetzungsmöglichkeit.
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Di 22.02.11 11:20
Martok hat folgendes geschrieben : | Stimmt, aber er probiert ja genau das Gegenteil: TBar-Objekt in TMergeable-Variable. |
Er übergibt eine TBar-Variable an die Methode, also zeigt der TMergeable-Parameter auf diese Variable. Und wenn er diesem Parameter nun innerhalb der Klasse ein TMergeable-Objekt zuweisen würde  ...
Man kann es auch so sehen: Der Typ der übergebenen Variable muss kovariant zu einem In-Parameter sein und kontravariant zu einem Out-Parameter (einem out TBar kann ich auch eine TMergeable-Variable übergeben), also sind var-Parameter logischerweise invariant.
jaenicke hat folgendes geschrieben : | Flamefire hat folgendes geschrieben : | Definiere ich die Funktion so:
Delphi-Quelltext 1:
| procedure RegisterMerge(var aWhat:PMergeable); overload; |
und rufe die mit RegisterMerhe(@Bar) auf ist alles ok. Aber ist unschön mit dem @ | Das finde ich noch nicht einmal. Denn dadurch sieht man zumindest, dass das Objekt neu zugewiesen werden könnte. Am Namen der Prozedur lässt sich das ja nicht wirklich erkennen... |
Und das var hat das nicht signalisiert  ?
_________________ >λ=
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 22.02.11 11:46
|
|
Flamefire 
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: Di 22.02.11 12:55
Es geht darum, Objekte zu "mergen" also zusammenzuführen. Damit das ganze auch über mehrere Vererbungsstufen einfach funktioniert, registriere ich einfach alles, was gemergt werden soll. Das ganze getrennt nach Strings, einfachen Datentypen und TMergeable Objekten. Damit ich (besonders bei Strings und Objekten) auch am Ende die tatsächliche Instanz habe brauche ich natürlich einen Zeiger auf den String/Objekt.
Sieht am Ende ungefähr so aus:
Delphi-Quelltext 1: 2: 3: 4: 5:
| procedure TLSMergeable.RegisterMerge(aWhat: PLSMergeable); begin if(not Assigned(FMergeObjs)) then FMergeObjs:=TList<PLSMergeable>.Create; FMergeObjs.Add(aWhat); end; |
und dann:
Delphi-Quelltext 1: 2: 3:
| if(Assigned(FMergeObjs)) then for i := 0 to FMergeObjs.Count - 1 do FMergeObjs[i]^.Merge(TLSMergeable(AOther).FMergeObjs[i]^); |
Macht das ganze doch etwas übersichtlicher, als in jedem Objekt die Merge Methode zu implementieren und dann alles einzeln zu kopieren. Ist mir zuviel tipparbeit 
|
|
|