Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Funktionen durchschleifen
tacl - Fr 16.07.10 09:33
Titel: Funktionen durchschleifen
Hi Leute,
ich glaub ich steh grad nur kräftig auf'm Schlauch und hoffe, dass mir jemand helfen kann.
Innerhalb einer Klasse definiere ich ein Feld, dass ich von klasseneigenen Methoden bearbeiten lassen möchte.
Eine Bearbeitung von ausserhalb der Instanz möchte ich verhindern. Jedoch soll das Feld möglichst ohne den Umweg über eine Methode ausgelesen werden können.
Die Symbole private und protected sind ja ungeeignet, da der Lesezugriff ja auch gesperrt wird.
Hat jemand die Lösung für mich?
Danke und Gruß
Patrick
Hidden - Fr 16.07.10 09:39
hi :)
Vielleicht kannst du den Zugriff über eine property gestalten:
Delphi-Quelltext
1: 2: 3: 4:
| private FMyField: TMyField; public property rOnly: TMyField read FMyField ; |
Propertys sind auch deshalb praktisch, weil man so später sehr einfach das Auslesen beispielsweise doch noch durch eine Funktion filtern lassen kann: Einfach read FMyField durch den Namen einer Funktion mit Rückgabewert TMyField ersetzen(sollte private/protected deklariert sein).
Hätte man die Funktion als public deklariert, müsste man für eine spätere Änderung des Aufrufs jeden einzelnen Aufruf getrennt umschreiben - von a := xyz auf P(xyz).
lg,
Narses - Fr 16.07.10 09:49
Moin!
Ich denke, das ist nicht das, was er möchte. Vermutlich geht es um den Inhalt des Feldes, der soll read-only sein. AFAIK geht das nicht, wenn du das Feld rausreichst (und nicht nur ein Element per Index/Methode), dann geht immer beides, Lesen und Schreiben. :nixweiss:
cu
Narses
Hidden - Fr 16.07.10 10:07
Wenn es sich bei dem Feld um ein Array oder einen ähnlichen, auf Pointern basierenden Typ geht, hast du recht,
Narses. Da muss dann eine Funktion mit Argument her(Index übergeben). Die kann aber auch über eine Property gekapselt werden, und der Aufruf erfolgt wie bei Arrays.
Einfach gestrickte Prozeduren und Funktionen dürften vom Compiler aber inline umgesetzt werden, d.h. du bekommst unter Umständen sogar den selben Assembler-Code wie bei direktem Zugriff auf das Array oder hast zumindest kein push und call drin.
Ich habe
tacl jetzt aber so verstanden, dass es sich bei dem
Feld um eine Feldvariable handelt, also eine wie oben gezeigt in der Klasse deklarierten. Das ist dann genau der Anwendungsfall für Propertys.
lg,
tacl - Fr 16.07.10 10:41
Hallo zusammen,
vielen Dank für Eure Antworten!
Der Weg über eine Property ist wie für mich gemacht, da der Weg der Befüllung über einen gekoppelten Funktionsaufruf
Delphi-Quelltext
1:
| property StrVersion: String read GetVersion; |
für mich absolut elegant ist. Die erste Lösung über ein Feld sah so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| type TConfig = class(TObject) StrVersion: String; private function GetVersion:String; public constructor Create; end; |
Die Befüllung hätte dann für alle Felder im Constructor erfolgen müssen.
Da der Zugriff auf eine Property genauso erfolgt wie auf ein Feld, muss ich im vorgelagerten Quelltext nicht einmal etwas ändern.
Vielen Dank!!
Patrick
Narses - Fr 16.07.10 11:14
Moin!
OK, ich hab´s falsch verstanden, es ging also doch nicht um ein "Feld" (=array). :idea: ;)
cu
Narses
tacl - Fr 16.07.10 11:20
Hi!
Nein, in diesem Fall ging es nicht um ein Array. Vor einem ähnlichen Problem werde ich wohl nächste Woche stehen,
wenn ich mich an den Errorhandler für mein Projekt begebe. :roll:
jaenicke - Sa 24.07.10 09:50
Es gibt auch so etwas:
Delphi-Quelltext
1: 2: 3: 4:
| private function GetData(Index: Integer): string; property Data[Index]: string read GetData; |
Zudem kannst du, wenn du eine Klasse zurücklieferst, innerhalb dieser Klasse wiederum den Zugriff sperren. Dort gibt es die Möglichkeit über Interfaces private und protected Methoden nach außen sichtbar zu machen. Wenn man dann über die normale Klasse von außen zugreift, kommt man nicht heran, wenn man über das Interface zugreift schon.
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: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
| type ITestClassFullAccess = interface procedure SetTest(const Value: string); end;
TTestClass = class(TInterfacedObject, ITestClassFullAccess) private FTest: string; protected procedure SetTest(const Value: string); function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; public property Test: string read FTest; end;
implementation
function TTestClass.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE; end;
function TTestClass._AddRef: Integer; begin Result := 1; end;
function TTestClass._Release: Integer; begin Result := 1; end;
procedure TTestClass.SetTest(const Value: string); begin FTest := Value; end; |
Das Interface kannst du auch in eine andere Unit packen, damit man diese einbinden muss um Schreibzugriff zu bekommen. Jedenfalls kannst du dann das machen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| var a: TTestClass; begin a := TTestClass.Create(); try ITestClassFullAccess(a).SetTest('aaa'); ShowMessage(a.Test); finally a.Free(); end; |
Ohne das Interface kommst du nur lesend an die Klasse heran.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 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!