Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Auf Objekte nur zugreifen, wenn Assigned and Erstellt
Jakob Schöttl - So 08.04.07 14:02
Titel: Auf Objekte nur zugreifen, wenn Assigned and Erstellt
Hallo mal wieder,
Ich habe eine Klasse, die eine Eigenschaft besitzt vom
TEdit. Eine Instanz von
TEdit soll von anderen Programmteilen erstellt und zugewiesen werden. Das bedeutet, dass auch andere Programmteile das Objekt freigeben können -> Exception!
Aber was ist, wenn jetzt meine Klasse auf das Edit zugreift, obwohl gar keine Instanz von
TEdit existiert?
Bis jetzt hab ich es so gemacht:
Delphi-Quelltext
1:
| if Assigned(Self.Edit) then Self.Edit.Text := 'Test'; |
Aber das reicht leider nicht, weil wenn ich
Self.Edit.Free aufrufe, dann zeigt
Self.Editimmer noch auf ein Objekt, das aber nicht mehr existiert.
Folge: Zugriffsverletzung.
Gibt es eine Funktion, die mir sagt, o
b der Objektzeiger zugewiesen ist und das Objekt existiert?
BenBE - So 08.04.07 14:12
Deshalb benutzt man zum Freigeben auch die Funktion FreeAndNil(Self.Edit);
HelgeLange - So 08.04.07 14:15
ausserdem sollte man sich, wenn man Komponenten schreibt, die sich andere Komponenten zuweisen lassen, eine Methode implementieren, die Notification heisst, dort einfach schaun, ob Operation = opRemove ist, dann testen, ob AComponent dein Edit ist und wenn ja, dann kannst deinen internen zeiger auf nil setzen, weil das edit gleich ins nirvana geschickt wird
Jakob Schöttl - So 08.04.07 15:01
mh, dann kann ich wohl nichts anderes machen, als auf Exceptionen zu reagieren.
In meinem Fall ist die Klasse ein Thread, es sieht so aus:
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: 26:
| type TLeseThread = class(TThread) private FSerial: TSerial; protected procedure Execute; override; public property Serial: TSerial read FSerial write FSerial; end;
implementation
procedure TLeseThread.Execute; var chr: char; begin While not Terminated do if Assigned(FSerial) then if FSerial.TryReadChar(chr) then begin end; end;
end. |
Komischerweise gibt es gar nicht gleich eine Exception, wenn ich von einer anderen Unit aus mit
LesenThread.Serial.Free das Objekt freigebe, obwohl in
Execute dieses Objekt die ganze Zeit genutzt wird...
BenBE - So 08.04.07 15:40
Hat jemand mal n paar Steine und ne Peitsche, um den Autor dieses Sources zu St\Peinigen?
OBJEKT-PROPERTIES NIE ÜBER DIREKTE FELDZUGRIFFE!!!Erzeuge für deine Komponente für diese Eigenschaft separate Getter und Setter-Methoden, dann kannst Du auch entsprechend drauf reagieren...
Ferner:
KOMPONENTEN AUF DIE EIN OBJEKT ANGEWIESEN IST, NIEMALS!!! DURCH FREMDOBJEKTE FREIGEBEN!!!Wenn Du ein Unlink vornehmen willst, dann:
Delphi-Quelltext
1: 2: 3:
| Serial := ThreadKompo.Serial; ThreadKompo.Serial := nil; FreeAndNil(Serial); |
Dann funktioniert nämlich auch das Freigeben problemlos!!!
JayEff - So 08.04.07 15:58
BenBE hat folgendes geschrieben: |
Hat jemand mal n paar Steine und ne Peitsche, um den Autor dieses Sources zu St\Peinigen? |
...Dass du immer gleich so brutal werden musst! :shock:
Nur könntest du vielleicht zur Verdeutlichung (Damit sogar ich es verstehe :roll: ) ein kleinens Sourcebeispiel hierzu bringen?
BenBE hat folgendes geschrieben: |
OBJEKT-PROPERTIES NIE ÜBER DIREKTE FELDZUGRIFFE!!!
Erzeuge für deine Komponente für diese Eigenschaft separate Getter und Setter-Methoden, dann kannst Du auch entsprechend drauf reagieren... |
BenBE - So 08.04.07 16:33
JayEff hat folgendes geschrieben: |
Nur könntest du vielleicht zur Verdeutlichung (Damit sogar ich es verstehe :roll: ) ein kleinens Sourcebeispiel hierzu bringen?
BenBE hat folgendes geschrieben: | OBJEKT-PROPERTIES NIE ÜBER DIREKTE FELDZUGRIFFE!!!
Erzeuge für deine Komponente für diese Eigenschaft separate Getter und Setter-Methoden, dann kannst Du auch entsprechend drauf reagieren... |
|
Darf ich F1 sagen?
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: 26: 27: 28: 29: 30:
| Type TThreadEx = class(TThread) Private FSerial: TSerial; function GetSerial: TSerial; procedure SetSerial(Const Value: TSerial); Public property Serial: TSerial Read GetSerial write SetSerial; end;
procedure TThreadEx.SetSerial(Const Value: TSerial); Begin If Not Assigned(Value) Then Begin end; FSerial := Value; end;
Function TThreadEx.GetSerial: TSerial; begin Result := FSerial; end; |
Der Getter sieht zwar erstmal sinnlos aus, verhindert aber den direkten Zugriff auf die Variable FSerial, wodurch unbefugte Manipulationen wie diese für TApplication.Mainform möglich sind, verhindert werden (und damit die Nutzung des Setters erzwungen wird.
Edit: Innerhalb der Komponente sollten nur Create und Destroy außer den beiden Setter\Getter-Methoden direkt auf die Variable FSerial zugreifen. Jeglicher andere Source sollte Serial (das Property) nutzen.
Jakob Schöttl - So 08.04.07 19:28
Kannst du mir mal ein Stichwort für F1 geben, bitte? Dann kann ichs mir da nochmal anschauen.
Aber der Code sieht schon mal ganz nützlich aus - Danke!
Bloß ein Problem: Das Objekt muss in anderen Units verwendet werden! Dazu benutze ich natürlich einen anderen Zeiger. Es muss deswegen woanders verwendet werden, weil dieser Thread für das dauernde Lesen von RS 232 zuständig ist, für das Schreiben aber nicht. Und zwei Objekte von TSerial kann ich nicht verwenden, sonst ist kein Zugriff von beiden auf die Schnittstelle möglich.
Jakob Schöttl - So 08.04.07 19:32
Mir fällt gerade ein, Ich könnte doch auch eine Thread-Methode für das Schreiben machen, oder nicht? Kann ein Thread Execute ausführen, und gleichzeitig andere Thread-Methoden aufgerufen werden. Ja, zB. Terminate
BenBE - So 08.04.07 19:53
Ja. Können sie. Ach ja: Was denkst Du, wozu der Setter eines Properties zuständig ist?
Jakob Schöttl - So 08.04.07 19:54
BenBE hat folgendes geschrieben: |
Delphi-Quelltext 1: 2: 3: 4:
| Function TThreadEx.GetSerial: TSerial; begin Result := FSerial; end; |
Der Getter sieht zwar erstmal sinnlos aus, verhindert aber den direkten Zugriff auf die Variable FSerial, wodurch unbefugte Manipulationen wie diese für TApplication.Mainform möglich sind, verhindert werden (und damit die Nutzung des Setters erzwungen wird. |
das stimmt leider nicht ganz, weil wenn ich zur SetMethode noch
ShowMessage schreibe und eine Eigenschaft ändere, dann wird keine
ShowMessage angezeigt.
HelgeLange - So 08.04.07 20:04
naja, wenn man eine get methode hat und doch an dem objekt von ausserhalb spielen will, dann macht mans ich einfach ne variable und weisst diese zu, dann kann man spielen, bis man schwarz wird. Ausserdem finde ich, dass das Spielen dazugehört, Delphi muss manchmal vergewaltigtw erden, damit es sich ordentlich verhält, allerdings sollte man eben auch wissen, was man macht
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!