Autor Beitrag
tacl
Hält's aus hier
Beiträge: 13

WinXP, Linux, OS/2
Delphi2/2010 Prof., FoxPro, C++
BeitragVerfasst: Fr 16.07.10 09:33 
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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2242
Erhaltene Danke: 55

Win10
VS Code, Delphi 2010 Prof.
BeitragVerfasst: Fr 16.07.10 09:39 
hi :)

Vielleicht kannst du den Zugriff über eine property gestalten:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
private
  FMyField: TMyField;
public
  property rOnly: TMyField read FMyField {write 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,

_________________
Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: 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

_________________
There are 10 types of people - those who understand binary and those who don´t.
Hidden
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2242
Erhaltene Danke: 55

Win10
VS Code, Delphi 2010 Prof.
BeitragVerfasst: 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, user profile iconNarses. 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 user profile icontacl 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,

_________________
Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
tacl Threadstarter
Hält's aus hier
Beiträge: 13

WinXP, Linux, OS/2
Delphi2/2010 Prof., FoxPro, C++
BeitragVerfasst: 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

ausblenden Delphi-Quelltext
1:
property StrVersion: String read GetVersion;					


für mich absolut elegant ist. Die erste Lösung über ein Feld sah so aus:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: 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

_________________
There are 10 types of people - those who understand binary and those who don´t.
tacl Threadstarter
Hält's aus hier
Beiträge: 13

WinXP, Linux, OS/2
Delphi2/2010 Prof., FoxPro, C++
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 24.07.10 09:50 
Es gibt auch so etwas:
ausblenden 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.
ausblenden volle Höhe 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

{ TTestClass }

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// no reference counting neccessary
end;

function TTestClass._Release: Integer;
begin
  Result := 1// no reference counting neccessary
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:
ausblenden 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.