Toon posts:

[Delphi] Published property probleem

Pagina: 1
Acties:
  • 191 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Ik werk met Delphi 5 en kwam tijdens het werken aan iets een probleem tegen: het lijkt wel of de write specifier het niet doet. Hieronder even een stukje code van de klasse TTest waarin het probleem zich ook al voordoet:


Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
type
  TTest = class(TComponent)
  private
    FLines: TStrings;
    procedure SetLines(Value: TStrings);
  public
    constructor Create;
  published
    property Lines: TStrings read FLines write SetLines;
  end;

  ...

constructor TTest.Create;
begin
  FLines := TStringList.Create;
end;

procedure TTest.SetLines(Value: TStrings);
begin
  ShowMessage('Waarom komt-ie hier niet?');
  FLines.Assign(Value);
end;


En hier maak ik een instantie van die klasse aan en voeg een woordje toe:

Delphi:
1
2
3
4
5
6
7
procedure TForm1.Button1Click(Sender: TObject);
var
  Test: TTest;
begin
  Test := TTest.Create;
  Test.Lines.Add('tekst');
end;


Het gekke is, dat-ie dus wel het woordje "tekst" toevoegd, maar nooit bij m'n ShowMessage komt. Ik kan het stukje FLines.Assign(Value); zelfs weghalen uit de SetLines methode en nog steeds voegt-ie het woordje goed toe! Het lijkt wel of ie mijn read en write instructies gewoon negeert. (Da's dus het frustrerende: als je code iets anders doet, dan wat-ie volgens de code zou moeten doen)

Heeft iemand enig idee wat ik fout doe?

  • whoami
  • Registratie: December 2000
  • Laatst online: 24-08 16:37
Waarom maak jij zoweel gebruik van een write - property en een SetFunction voor die FLines?
Je kan toch evengoed zeggen:
code:
1
property Lines : TStrings read FLines write FLines;


Ik snap niet goed waarom je daar nog een set-method voor gebruikt.... IMHO gebruik je ofwel getters/setters ofwel properties...

https://fgheysels.github.io/


Verwijderd

Ik vermoed dat ie die setlines alleen uitvoert als je de Lines zou zetten, je moet de .Add method overriden van de TStrings om te bereiken wat jij wilt.

Probeer in die testbutton code dit is :
code:
1
2
3
4
5
6
7
procedure TForm1.Button1Click(Sender: TObject);
var
  MyLines :  TStrings;
begin
  MyLines := TStringList.Create;
 Test.Lines := MyLines;
 end;

ff uit het hoodd (zonder compiler), nu zou ie die showmessage wel moeten doen.

Verwijderd

whoami schreef op 13 november 2002 @ 19:15:
Waarom maak jij zoweel gebruik van een write - property en een SetFunction voor die FLines?
Je kan toch evengoed zeggen:
code:
1
property Lines : TStrings read FLines write FLines;


Ik snap niet goed waarom je daar nog een set-method voor gebruikt.... IMHO gebruik je ofwel getters/setters ofwel properties...
Die getters/setters kunnen btw zeer handig zijn bij properties, waarom zou je een keuze moeten maken tussen getters/setters of properties ??

  • Eegee
  • Registratie: Januari 2000
  • Laatst online: 24-08 21:18
Ja, volgens mij doe je met Test.Lines (.add) een read op Test.Lines (dus je haalt FLines op). Vervolgens doe je add op wat je net gehaald hebt (een TStrings instantie). Dus je roept nooit Setlines aan op die manier. Alleen bij een :=, zoals maui71 zegt, wordt Setlines aangeroepen (bij een directe toewijzing)

Verwijderd

Topicstarter
whoami schreef op 13 November 2002 @ 19:15:
Waarom maak jij zoweel gebruik van een write - property en een SetFunction voor die FLines?
Je kan toch evengoed zeggen:
code:
1
property Lines : TStrings read FLines write FLines;


Ik snap niet goed waarom je daar nog een set-method voor gebruikt.... IMHO gebruik je ofwel getters/setters ofwel properties...
Ja je hebt helemaal gelijk. Ik wil natuurlijk nog het een en ander aan code uitvoeren in mijn SetLines methode: iets dat altijd uitgevoerd wordt als er wat verandert aan tekst. In dit geval heb ik er ShowMessage staan, maar daar komt natuurlijk nog wat anders.

  • whoami
  • Registratie: December 2000
  • Laatst online: 24-08 16:37
Verwijderd schreef op 13 november 2002 @ 19:18:
[...]


Die getters/setters kunnen btw zeer handig zijn bij properties, waarom zou je een keuze moeten maken tussen getters/setters of properties ??


Nouja, ik zeg niet dat hij dat moet doen. Het was gewoon IMHO....

https://fgheysels.github.io/


Verwijderd

Topicstarter
Verwijderd schreef op 13 november 2002 @ 19:16:
Ik vermoed dat ie die setlines alleen uitvoert als je de Lines zou zetten, je moet de .Add method overriden van de TStrings om te bereiken wat jij wilt.
...
ff uit het hoodd (zonder compiler), nu zou ie die showmessage wel moeten doen.
maui71, je hebt helemaal gelijk! De code:

Delphi:
1
2
3
4
5
6
7
8
9
procedure TForm1.Button1Click(Sender: TObject);
var
  Test: TTest;
  MyLines: TStrings;
begin
  Test := TTest.Create;
  MyLines := TStringList.Create;
  Test.Lines := MyLines;
end;


werkt wel! Alleen...het moet toch mogelijk zijn niet alle 100 methodes van een TStringList te overriden? In principe moet het mogelijk zijn voor de programmeur die m'n klasse gaat gebruiken elke willekeurige functie kan gebruiken (zoals, Add, Delete, Clear, Insert, etc.), maar dat ervoor of erna een stukje code van mij wordt uitgevoerd?

Verwijderd

whoami schreef op 13 November 2002 @ 19:20:

[...]


Nouja, ik zeg niet dat hij dat moet doen. Het was gewoon IMHO....
Ik viel je niet aan hoor :*)

Maar ik gebruik vrij vaak setters/getters (vooral setters) voor properties, op die manier kan je heel handig centrale code regelen voor als een propertie van waarde veranderd (imho).
:P

Verwijderd

Verwijderd schreef op 13 November 2002 @ 19:25:
[...]


maui71, je hebt helemaal gelijk! De code:

Delphi:
1
2
3
4
5
6
7
8
9
procedure TForm1.Button1Click(Sender: TObject);
var
  Test: TTest;
  MyLines: TStrings;
begin
  Test := TTest.Create;
  MyLines := TStringList.Create;
  Test.Lines := MyLines;
end;


werkt wel! Alleen...het moet toch mogelijk zijn niet alle 100 methodes van een TStringList te overriden? In principe moet het mogelijk zijn voor de programmeur die m'n klasse gaat gebruiken elke willekeurige functie kan gebruiken (zoals, Add, Delete, Clear, Insert, etc.), maar dat ervoor of erna een stukje code van mij wordt uitgevoerd?
Ik denk dat je dan eerst ff TStringlist (of TStrings ?) moet subclassen.

  • whoami
  • Registratie: December 2000
  • Laatst online: 24-08 16:37
*Ahum*
Er bestaat ook zoiets als een edit knop hoor maui71....

https://fgheysels.github.io/


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Verwijderd schreef op 13 November 2002 @ 19:25:
werkt wel! Alleen...het moet toch mogelijk zijn niet alle 100 methodes van een TStringList te overriden? In principe moet het mogelijk zijn voor de programmeur die m'n klasse gaat gebruiken elke willekeurige functie kan gebruiken (zoals, Add, Delete, Clear, Insert, etc.), maar dat ervoor of erna een stukje code van mij wordt uitgevoerd?
Dan moet je een eigen afgeleide maken van TStrings(List) en daar alleen de methods overriden die jij nodig hebt. Bestudeer daarvoor even de classe. TStrings.Add maak uiteindelijk ook gebruik van Insert, dus het is niet zo dat je alles hoeft te overriden.

Waarom zou je willen weten of er iets is veranderd in je TStrings? Misschien dat een andere oplossing veel netter is.

We adore chaos because we like to restore order - M.C. Escher


Verwijderd

LordLarry schreef op 14 november 2002 @ 09:10:
[...]


Dan moet je een eigen afgeleide maken van TStrings(List) en daar alleen de methods overriden die jij nodig hebt. Bestudeer daarvoor even de classe. TStrings.Add maak uiteindelijk ook gebruik van Insert, dus het is niet zo dat je alles hoeft te overriden.

Waarom zou je willen weten of er iets is veranderd in je TStrings? Misschien dat een andere oplossing veel netter is.
Dan moet je iets maken als:
Delphi:
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
type
  TTest = class(TComponent)
  private
    FLines: TStringList;
    procedure  ListBeforeChange(Sender:Object);
    procedure ListAfterChange(Sender:TObject);
  public
    constructor Create;
  published
    property Lines: TStrings read FLines write FLines;
  end;

  ...

constructor TTest.Create;
begin
  FLines := TStringList.Create;
  FLines.OnChanging:=ListBeforeChange;
  FLines.onChange:=ListAfterChange;
  
end;

procedure TTest.ListBeforeChange(Sender:TObject);
begin
  ShowMessage('Er gaat iets in de stringlist veranderd worden');
end;

procedure TTest.ListAfterChange(Sender:TObject);
begin
  ShowMessage('Er is iets in de stringlist veranderd');
end;

Ik heb het niet getest in de compiler, maar dit geeft een aanzetje

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 08:23

Tomatoman

Fulltime prutser

Aegis, je doet het helemaal goed. Ook het gebruik van de write modifier SetLines is goed. Op die manier weet je zeker dat het object dat je met TStringList.Create maakt, uiteindelijk weer wordt opgeruimd met FLines.Free. Als je
Delphi:
9
    property Lines: TStrings read FLines write FLines;
zou hebben geschreven en je zou bijvoorbeeld de code Test.Lines := nil; uitvoeren, zou FLines de waarde nil krijgen, maar zou de TStringList niet worden vernietigd! Resultaat: memory leak. Nogmaals, wat jij doet met SetLines en FLines.Assign(Value) is de juiste weg.

Nu het antwoord op je vraag. Als je bijvoorbeeld schrijft Test.Lines.Text := 'tekst'; wordt de property Lines gelezen (via de read specifier) om het object te verkrijgen. Vervolgens wordt write specifier van de property Text (van het zojuist verkregen Lines object) uitgevoerd. Kortom, de write specifier van Lines wordt nooit gebruikt.

Dat kan ik ook aantonen. Haal de write specifier van Lines maar eens weg:
Delphi:
9
    property Lines: TStrings read FLines;
Je zult zien dat je code dan nog steeds zonder problemen compileert. Het enige probleem is dat read-only properties niet in de Object Inspector verschijnen, dus daarom is die SetLines write specifier van jou toch wel erg handig - daarmee maak je Lines 'zichtbaar' in de Object Inspector.

Een goede grap mag vrienden kosten.


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

tomatoman schreef op 14 november 2002 @ 12:10:
Het enige probleem is dat read-only properties niet in de Object Inspector verschijnen
Kleine verbetering: Sinds Delphi 6 kan je er voor kiezen ook (published) readonly properties in je inspector te laten verschijnen. Default staat het alleen uit.

We adore chaos because we like to restore order - M.C. Escher

Pagina: 1