Recent

Author Topic: [solved] Iteration of class fields  (Read 5233 times)

Joanna

  • Hero Member
  • *****
  • Posts: 815
[solved] Iteration of class fields
« on: April 11, 2024, 01:33:37 am »
Code: Pascal  [Select][+][-]
  1. Myclass = class
  2. Lbl:tlabel;
  3. Edit:tedit;
  4. Button:tbutton;
  5. End;
  6.  
  7.  
Assuming that none of these are created until runtime . Is there an elegant way to iterate through them and create them? Yes I know i can iterate through controls list after creation. But is there a way to check class fields for nil and create them?
« Last Edit: April 16, 2024, 01:46:29 am by Joanna »
✨ 🙋🏻‍♀️ More Pascal enthusiasts are needed on IRC .. https://libera.chat/guides/ IRC.LIBERA.CHAT  Ports [6667 plaintext ] or [6697 secure] channel #fpc  Please private Message me if you have any questions or need assistance. 💁🏻‍♀️

Thaddy

  • Hero Member
  • *****
  • Posts: 14849
  • Censorship about opinions does not belong here.
Re: Iteration of class fields
« Reply #1 on: April 11, 2024, 07:27:45 am »
assigned()
Remember the Medway disaster..

Joanna

  • Hero Member
  • *****
  • Posts: 815
Re: Iteration of class fields
« Reply #2 on: April 11, 2024, 08:16:16 am »
Assigned() Checkes if it’s nil I presume.
Is it possible to iterate through Class fields?
✨ 🙋🏻‍♀️ More Pascal enthusiasts are needed on IRC .. https://libera.chat/guides/ IRC.LIBERA.CHAT  Ports [6667 plaintext ] or [6697 secure] channel #fpc  Please private Message me if you have any questions or need assistance. 💁🏻‍♀️

Thaddy

  • Hero Member
  • *****
  • Posts: 14849
  • Censorship about opinions does not belong here.
Re: Iteration of class fields
« Reply #3 on: April 11, 2024, 08:30:40 am »
Assigned() Checkes if it’s nil I presume.
Is it possible to iterate through Class fields?
in your example, yes, provided that the container class is instantiated, you can use assigned() on the contained components.
Remember the Medway disaster..

rvk

  • Hero Member
  • *****
  • Posts: 6268
Re: Iteration of class fields
« Reply #4 on: April 11, 2024, 09:05:56 am »
Assuming that none of these are created until runtime . Is there an elegant way to iterate through them and create them? Yes I know i can iterate through controls list after creation. But is there a way to check class fields for nil and create them?
If you want this dynamically without knowing the names of the fields you would need RTTI.

Have a look at this topic. https://forum.lazarus.freepascal.org/index.php?topic=39791.0
It has some code example normally used for Delphi but maybe someone can translate it for FPC, it that is what you meant with your question.
(Back in 2018 when that topic was created RTTI wasn't yet implemented fully).

assigned()
How is this related to ITERATION of the class fieds. It's just checking if they exists but you would need to do this separate with each field. The question was... how can you ITERATE through them !!
« Last Edit: April 11, 2024, 09:09:18 am by rvk »

alpine

  • Hero Member
  • *****
  • Posts: 1141
Re: Iteration of class fields
« Reply #5 on: April 11, 2024, 09:20:04 am »
Assuming that none of these are created until runtime . Is there an elegant way to iterate through them and create them? Yes I know i can iterate through controls list after creation. But is there a way to check class fields for nil and create them?
If you want this dynamically without knowing the names of the fields you would need RTTI.

Have a look at this topic. https://forum.lazarus.freepascal.org/index.php?topic=39791.0
It has some code example normally used for Delphi but maybe someone can translate it for FPC, it that is what you meant with your question.
(Back in 2018 when that topic was created RTTI wasn't yet implemented fully).
Perhaps a custom enumerator can be defined, based on the RTTI. But where is the point when each of them needs to be created by its own factory and then customized separately?
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

rvk

  • Hero Member
  • *****
  • Posts: 6268
Re: Iteration of class fields
« Reply #6 on: April 11, 2024, 09:32:40 am »
Perhaps a custom enumerator can be defined, based on the RTTI. But where is the point when each of them needs to be created by its own factory and then customized separately?
Creation should be possible through the classtype. Assuming some common elements like owner and parent you could initialize those too. Other fields could be customized on class basis.

But yes, it might be useful to have more info about the use-case.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11600
  • FPC developer.
Re: Iteration of class fields
« Reply #7 on: April 11, 2024, 09:57:20 am »
(Back in 2018 when that topic was created RTTI wasn't yet implemented fully).

_published_ RTTI worked since the 199xs.  See Tcomponent.readcomponent* and its helpers outside of tcomponent in rtl/objpas/classes.

The new RTTI (unit) is for the extra RTTI for non published properties that was introduced with IIRC D2010, and turned on globally with Delphi XE 2.

Thaddy

  • Hero Member
  • *****
  • Posts: 14849
  • Censorship about opinions does not belong here.
Re: Iteration of class fields
« Reply #8 on: April 11, 2024, 10:00:38 am »
Just in case Joanna indeed really creates the components dynamically: in that case the component will not be present in the component list. Example assumes a button and a form:
Code: Pascal  [Select][+][-]
  1. function CreateUniqueName(const BaseName: string; Owner: TComponent): string;
  2. var
  3.   Counter: Integer;
  4. begin
  5.   Counter := 1;
  6.   Writestr(Result,BaseName,Counter);
  7.   while Assigned(Owner.FindComponent(Result)) do
  8.   begin
  9.     Writestr(Result,BaseName,Counter);
  10.     Inc(Counter);
  11.   end;
  12. end;
  13.  
  14. procedure TForm1.Button1Click(Sender: TObject);
  15. begin
  16.    with tbutton.create(form1) do
  17.    begin
  18.      parent := form1;
  19.      { strip the T from the classname }
  20.      name :=CreateUniqueName(copy(classname,2,length(classname)), form1);
  21.      align:=altop;
  22.      visible :=true;
  23.      OnClick  := @Button1Click;
  24.    end;
  25. end;
       
« Last Edit: April 11, 2024, 11:31:15 am by Thaddy »
Remember the Medway disaster..

rvk

  • Hero Member
  • *****
  • Posts: 6268
Re: Iteration of class fields
« Reply #9 on: April 11, 2024, 10:18:07 am »
(Back in 2018 when that topic was created RTTI wasn't yet implemented fully).

_published_ RTTI worked since the 199xs.  See Tcomponent.readcomponent* and its helpers outside of tcomponent in rtl/objpas/classes.

The new RTTI (unit) is for the extra RTTI for non published properties that was introduced with IIRC D2010, and turned on globally with Delphi XE 2.

For Delphi 10+ something like this simply works. I Lazarus it doesn't produce anything.

Code: Pascal  [Select][+][-]
  1. uses rtti;
  2.  
  3. type
  4.   TMyClass = class
  5.     Lbl: TLabel;
  6.     Edit: tedit;
  7.     Button: TButton;
  8.   end;
  9.  
  10. procedure TForm1.FormCreate(Sender: TObject);
  11. var
  12.   context: TRttiContext;
  13.   rType: TRttiType;
  14.   Field: TRttiField;
  15. begin
  16.   context := TRttiContext.Create;
  17.   rType := context.GetType(TMyClass.ClassInfo);
  18.   for Field in rType.GetFields do
  19.       Memo1.Lines.Add(Field.Name);
  20. end;

Quote
Lbl
Edit
Button

So the question is... is this already possible with the rtti from Lazarus???
« Last Edit: April 11, 2024, 10:23:10 am by rvk »

Thaddy

  • Hero Member
  • *****
  • Posts: 14849
  • Censorship about opinions does not belong here.
Re: Iteration of class fields
« Reply #10 on: April 11, 2024, 11:00:18 am »
Of course and without RTTI, see my example above.

But with RTTI this should be possible in trunk with maybe small changes because the extended RTTI is similar to Delphi but not equal, 100% compatible.
I do not see anything in your code snippet that would not work.
« Last Edit: April 11, 2024, 11:04:48 am by Thaddy »
Remember the Medway disaster..

rvk

  • Hero Member
  • *****
  • Posts: 6268
Re: Iteration of class fields
« Reply #11 on: April 11, 2024, 11:04:43 am »
Of course and without RTTI, see my example above.
I don't see how the class mentioned in the openingspost would have a componentcount or even an owner. It's just a class with fields/elements.

But you could argue why this is constructed like this... you could also use a record or something. So the actual use-case would be important to know.

Code: Pascal  [Select][+][-]
  1. type
  2.   TMyClass = class
  3.     Lbl: TLabel;
  4.     Edit: tedit;
  5.     Button: TButton;
  6.   end;

Thaddy

  • Hero Member
  • *****
  • Posts: 14849
  • Censorship about opinions does not belong here.
Re: Iteration of class fields
« Reply #12 on: April 11, 2024, 11:06:33 am »
@RvK our posts crossed, you may examine my edit?
Remember the Medway disaster..

rvk

  • Hero Member
  • *****
  • Posts: 6268
Re: Iteration of class fields
« Reply #13 on: April 11, 2024, 11:09:30 am »
But with RTTI this should be possible in trunk with maybe small changes because the extended RTTI is similar to Delphi but not equal, 100% compatible.
I do not see anything in your code snippet that would not work.
I tried the code in Delphi and got the result below it.
Trying the same code in an empty project with a simple TMemo and pasting it in, results in an empty memo.

I use FPC and Lazarus trunk from 3 days ago.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11600
  • FPC developer.
Re: Iteration of class fields
« Reply #14 on: April 11, 2024, 11:24:40 am »
So the question is... is this already possible with the rtti from Lazarus???


  • Work in progress in FPC/trunk.
  • Not production yet, don't know exact status.
  • Might also require release engineering changes to actually enable it when compiling. You'll know when the EXEs double

 

TinyPortal © 2005-2018