![]() |
Type-Problem
Hallo zusammen,
ich passe gerade ein von Hagen ![]() Allerdings habe ich mit folgender Funktionalität Probleme:
Delphi-Quellcode:
Ich habe entgegen dem Beispiel noch die Unit "TypInfo" in die uses-Klausel mit aufgenommen, da das Beispiel ohne diese nicht funktioniert.
type
TModularForm = class(TForm) protected function GetParam(const Name: String): Variant; virtual; procedure SetParam(const Name: String; Data: Variant); virtual; public class procedure Register; // wir erweitern nun unser gemeinsammes Basis Interface //class function FormularName: String; virtual; abstract; //class function MenuPath: String; virtual; abstract; property Param[Name: String]: Variant read GetParam write SetParam; // <--- hier end; ... function TModularForm.GetParam(const Name: String): Variant; begin Result := TypInfo.GetVariantProp(Self, Name); end; procedure TModularForm.SetParam(const Name: String; Data: Variant); begin TypInfo.SetVariantProp(Self, Name, Data); end; Allerdings erhalte ich dann für die angegebene Zeile nun ein:
Delphi-Quellcode:
Gruß Igotcha
[Error] FormMain.pas(26): Incompatible types
|
Re: Type-Problem
Delphi-Quellcode:
Das ist ein Fehler, IMHO.
procedure SetParam(const Name: String; Data: Variant); virtual;
Du solltest es so machen:
Delphi-Quellcode:
procedure SetParam( Data: Variant); virtual;
|
Re: Type-Problem
Hmmm, ich habe das gerade als "Clou" interpretiert, dass ich mit
Delphi-Quellcode:
quasi eine "Allround-Möglichkeit" habe, um Properties innerhalb des gesamten Modulgeflechts setzen zu können...
procedure SetParam(const Name: String; Data: Variant); virtual;
Gruß Igotcha |
Re: Type-Problem
Muss Data nicht auch const sein?
|
Re: Type-Problem
Zitat:
Der Cursor landet genau hinter dem "write" in der o.g. Zeile. |
Re: Type-Problem
Tja, ich wusste das auch nicht was Borland da wiedermal geändert hat, so müsste es gehen:
Delphi-Quellcode:
Der Index einer Property, wenn er vom Typ LongString ist, muß anscheinend jetzt immer als const deklariert werden. Ansich ist das logisch, unlogisch ist nur das man zb. in D3 auch ohne const arbeiten konnnte (wenn ich mich recht erinnere).function GetParam(const Name: String): Variant; virtual; procedure SetParam(const Name: String; const Data: Variant); virtual; public class procedure Register; property Param[const Name: String]: Variant read GetParam write SetParam; end; Zitat:
Gruß Hagen |
Re: Type-Problem
Funktioniert jetzt, danke!
|
Re: Type-Problem
Hallo,
ich habe meinen Code auch von Hagen und hatte das selbe Problem. Nun funktioniert das soweit unter Delphi2006. Aber wie kann ich jetzt Werte übergeben? Über einen Button im MainForm rufe ich das nach dem Laden des Formulars auf:
Delphi-Quellcode:
Und danach teste ich anhand eines weiteren Buttons im Modul, ob der Wert übergeben wurde:
modul1.SetParam('test', Button1.Caption);
Delphi-Quellcode:
Leider gibt er mir aber bereits bei SetParam diese Fehlermeldung aus: Eigenschaft test existiert nicht
label1.caption := string(ModularForm1.GetParam('test'));
Wo muss man denn das noch definieren? Vielen Dank |
Re: Type-Problem
Zitat:
|
Re: Type-Problem
Hm, das wäre mir absolut neu. Mich interessiert als Refernez nur das was die RTTI und somit der Compiler kann. In TypInfo.pas kann man sehr wohl lesen, als verwendeter realer Source!!, das eine Property auch virtuelle Getter/Setter haben kann.
Das spielt aber auch keine Rolle wenn es nicht so wäre. Dann ändern wir es so um das die Getter/Stetter statisch sind und intern als Dispatcher an 2 virtuelle Methoden weiterreichen. Mich würde aber mal interessieren WO du das in der OH gelesen haben willst. Weil es dort nicht explizit steht und nur Beispiele mit statischen Methoden drinenstehen, heist dies noch lange nicht das es nicht geht. Ich programmiere seit es Delphi gibt (genauer seit BP4.0) und eine Setter/Getter Methode konnte schon immer statisch oder virtuell aber nicht dynamisch und somit ergo auch keine Nachrichtenmethode eg. als message deklariert sein. Sie darf sogar eine abstrakte Methode sein, und damit eben auch virtuell (abstrakte statische Methoden machen keinen Sinn). Aus Sicht der Logik ist es auch sinnvoll, wenn man schon überschreibbare Methoden kennt, die Setter/Getter Methoden, die ja wiederum nur ein weiteres Qualitätsmerkmal der OOP umsetzen -> Properties, ebenfalls virtualisieren zu können. Warum sollten gerade auf die neueren Properties nicht die Regeln der OOP gelten ? (das wäre ein unlogischer Schritt von Borland gewesen den ich wohl am meisten kritisieren würde). Das man die Getter/Setter nicht dynamisch deklarieren kann ist eine Frage von Effizienz im Code. Sie wären unnötig langsam und brächten keinen Vorteil da man zu 99.99% der Zeit eine Property mit Getter/Setter Methoden sofort implementiert, statt mit dem Ziele sie über dynamische Methoden erst viel später durchimplementieren zu wollen. Hier zählt also der Kompromis von Aufwand und Nutzen der gegen dynamsiche Setter/Getter spricht. Der Sinn einer dynamsichen Methode besteht in der OOP darin das der Initial Entwickler einen Schnittstellenrumpf vorgeben kann ohne diese real implementieren zu müssen. Im Falle der Properties sind dynmische Methoden absolut sinnfrei, bzw. zu 99.9% sinnfrei ;) Das man dabei aber diese Methoden nicht als Messagemethoden deklarieren kann ist ebenfalls sinnvoll da sie mit einem Messaging nichts zu tuen haben. Davon abgesehen sind Messagemethoden eng verknüpft mit den dynamischen Methoden, infakt es sind dynamische Methoden mit explizierter Angabe der Slotnummer der DMT im Source (früher in BP konnte man die Slotnummer auch bei normalen dynamsichen Methoden vorgeben, heute geht dies nicht mehr, schade). Ergo: da dynamische Setter/Getter nicht gehen, können auch Messagemethoden nicht funktionieren. Wie man sieht: die Regeln der OOP und wie die Borlanianer die VCL konstruiert haben unterwerfen sich zwingender Logik. Einer Logik die man selber nachvollziehen kann und mit der wir quasi schon erraten können was in der VCL geht oder nicht geht. Ich schlage bei sowas immer vor: einfach selber mal ausprobieren statt sich einfach auf Meinungen Andere zu verlassen (davon gibts nämlich ne Menge Pseudowissen). Gruß Hagen |
Re: Type-Problem
Zitat:
Die Setter/Getter Methode .SetParam() und .GetParam() sind deshalb virtuell weil der Entwickler die Möglichkeit hat ZWEI verschiedene Implementierungswege einzuschlagen. 1.) direkte Auswertung in den Getter/Setter Methoden der übergebenen Parameter. Das ist das was du in deiner .SetParam() Methode mit Label1.Caption := Data; gemacht hast. Du wertest den Parameter Index/Name garnicht selektiv aus. 2.) automatische Auswertung über Properties die über TypInfo und Variants erfolgt. DU hast also in deine Methode .GetParam() die Methode 2. gewählt ohne jedoch eine Property "Test" zu deklarieren. Im Setter .SetParam() wählst du Methode 1. und damit mischt du zwei grunverschiedene Implementierungswege. Die übrigens nur ein Vorschlag meinerseits waren. Gruß Hagen |
Re: Type-Problem
Zitat:
Zitat:
|
Re: Type-Problem
Die Delphi5-Hilfe enthält an dieser Stelle offenbar einen (Übersetzungs?)Fehler.
Zitat:
Zitat:
|
Re: Type-Problem
Ok, dann ist alles klar. Das mit dem überladen ist ja auch vollkommen nachvollziehbar. Ok, danke, dann wäre das geklärt. Nun ja, die Änderungen habe ich an dem Projekt nun schon gemacht, aber bei nächsten Projekten kann ich dann wieder virtuelle Getter/Setter nutzen (die ja, wie gesagt, einwandfrei funktioniert hatten - daher war ich damals recht erstaunt dies zu lesen).
|
Re: Type-Problem
Hallo Hagen,
danke für deine Antwort. Zitat:
Hier mal meine beiden Funktionen:
Delphi-Quellcode:
{Lade übergebene Variable}
function TModulForm.GetParam(const Name: String): Variant; begin Result := TypInfo.GetVariantProp(Self, Name); end; {Setze zu übergebende Variable} procedure TModulForm.SetParam(const Name: String;const Data: Variant); begin TypInfo.SetVariantProp(Self, Name, Data); end; Zitat:
Nun funktioniert das soweit mit Zahlen und Boolschen Properties. Aber bei Strings gibt mir Delphi beim Beenden des Programmes eine Zugriffsverletzung aus. 1. In der MainForm (Anker-Unit) rufe ich nach dem erstellen des Formulars des Moduls diesen Code auf: modul1.SetParam('VarString', 'Stringübergabe'); 2. Im Modul ist das ganze so deklariert:
Delphi-Quellcode:
Ich sehe dort keinen Fehler und trotzdem kommt eine EAccessViolation in module rtl100.bpl
TModulForm1 = class(TModulForm)
protected function GetParam(const Name: String): Variant; override; procedure SetParam(const Name: String;const Data: Variant); override; private //Deklarierung der Parameter für GetParam und SetParam FVarString : String; published //Deklarierung der Parameter für GetParam und SetParam property VarString : String read FVarString write FVarString; end; {...} function TModulForm1.GetParam(const Name: String): Variant; begin Result := inherited GetParam(Name); end; procedure TModulForm1.SetParam(const Name: String;const Data: Variant); begin // da wir das schon in der Basisklasse getan haben also einfach inherited SetParam(Name, Data); end; {...} //Aufruf erfolgt per Button in ein Label bfAusgabe.Caption := GetParam('VarString'); Kommt aber nur, sofern ich SetParam ausgeführt habe! Wenn ich nur GetParam ausführe und das Programm beende, kommt keine Fehlermeldung. Desweiteren bin ich noch am tüfteln, wie ich z.B. per Button im Modul die Caption des Moduls ändere. Man könnte Caption := 'Neuer Modultitel'; schreiben, aber wie kann ich das über den Modulnamen + Caption machen (in Form von Modulname.Caption) ? Vielen Dank für die Hilfe gruß Timelesk |
Re: Type-Problem
;) das meinte ich mit "traue niemals Leuten die nicht vom Fach sind". EIn Übersetzer versteht garnicht was er da übersetzt und der verantwortliche "Programmierer" hat garnicht die Zeit alles ins kleinste Detail zu überprüfen.
Deshalb zählen im Grunde die Dokumentationen in Form eines Sourcecodes, und es ist meine erste "Amtshandlung", wenn ich eine neue Delphi version bekomme, deren RTL Source zu lesen. Deshalb weis ich definitiv das Unit TypInfo.pas von allen Delphiversionen der Zugriff auf Property per RTTI virtuelle Methoden unterstützen. Überladene Methoden (overload) können bei Property nicht gehen, warum auch. Das würde bedeuten das das nur Sinn macht wenn man auch überladene Properties deklararien könnte. Das macht höchstens Sinn bei indizierten Array[] Properties. da nur bei deren Getter/Setter ein Parameter zur eindeutigen Indentifizierung des overloads vorhanden ist. Bekannntlich kann Delphi ja keine Overloads auf Funktionen in deren Parametersignatur nur der Resulttype unterschiedlich ist. Das würde auf normale Getter/Setter Methoden dann zutreffen. Wenn ichs mir aber recht überlege, dann wären überladene indizierbare Properties garnichtmal so schlecht. Sowas ginge dann
Delphi-Quellcode:
Hm, andererseits nimmt man dann halt einen Variant als Index.
type
THashTable = class private function GetItem(const Index: String): THashItem; virtual; overload; function GetItem(const Index: Int64): THashItem; virtual; overload; ... public property Item[const Index: String]: THashItem read GetItem write SetItem; overload; property Item[const Index: Int64]: THashItem read GetItem write SetItem; overload; end; Gruß Hagen |
Re: Type-Problem
Gut, denn
Zitat:
Vermutung meinerseits wäre es: a.) .SetParam('VarString', xyz); achte mal darauf das der Name der Property exakt ist. Das sollte eigentlich egal sein ob man Groß/Klein schreibt aber man weis ja nie was Borland so alles in den Units verändert mit den Versionen. b.) FormVariable.SetParam(); achte darauf das FormVariable auch ein gültiges TForm enthält c.) Unit Variants eventuell "schei.e" ? So oft arbeite ich nicht mit Varianten, aber ichw eis das je nach Delphiversionen es so einige Probleme geben sollte. Ich vermeide sie deshalb. Aber in Bezug auf mein Beispeil wäre sie die flexibelste Alternative. Ehrlicherweise muß ich zugeben das mein Beispiel aus den Erfahrungen eines parellelen Entwicktungsprozesses meines eigenen Modulsystemes entstand. Gruß Hagen |
Re: Type-Problem
Hallo Hagen,
vielen Dank für die schneller Antwort. Ich habe nun einfach mal in der TypInfo nach Variant gesucht und herausgefunden, dass die Funktionen GetPropValue und SetPropValue ebenfalls mit Varianten arbeiten und siehe da: Es funktioniert mit Strings! Zitat:
Und genau das ist ja mein Problem: im Hauptformular (in der auch die abgeleitete Klasse steht) wird ja das Package geladen und die Form über CreateModuleForm erstellt:
Delphi-Quellcode:
Jetzt kann ich von der Hauptform aus modul1.WindowState := wsMaximized schreiben und das klappt auch ganz schön :)
var modul1: TModulForm;
begin {...} modul1 := CreateModuleForm('TModulForm1'); end; Aber im Modul selbst, wie kann ich dort das Formular ansprechen? modul1 ist dort ja nicht registriert und wenn ich einfach ne Variable registrier ModulForm1 : TModulForm1, dann ist das ja nicht die Variable, welche auf mein Modul-Formular zeigt und ändert dementsprechend auch nichts ab. Aber genau das möchte ich erreichen, dass ich im Modul selbst das Formular des Moduls ansprechen kann. Ich hoffe, das war jetzt verständlich ;) Vielen Dank gruß Timelesk |
Re: Type-Problem
Im Modul selber greifst du OOP konform zu, dh. immer über Self. Niemals über die globale Variable ModulForm1: TModulForm1, da diese ja garnicht mehr benutzt wird und zudem ist der Zugriff, egal ob Modulbasiert oder in normalen Delphi Anwendung, über diese Variable generell kontraproduktiv. Wenn man sowas denoch benötigt muß man sich eben bessere Wege einfallen lassen als Programierer. Denn benutzt man diese Variable dann verhindert man damit das multiple Erzeugen von mehreren Formularen der gleichen Instanz.
Gruß Hagen |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:49 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