Recent

Author Topic: Array of Record as Property  (Read 1279 times)

Weitentaaal

  • Hero Member
  • *****
  • Posts: 503
  • Weitental is a very beautiful garbage depot.
Array of Record as Property
« on: June 28, 2022, 03:25:05 pm »
Hello,

how do i get this to work:

Code: Pascal  [Select][+][-]
  1. TSomeRecord = record
  2.    S1: String;
  3.    S2: String;
  4.    S3: String;
  5. end;
  6.  
  7. { TAClass }
  8. TAClass = class
  9.  
  10. private
  11.    fSomeArr: Array[0..1] of TSomeRecord;
  12.  
  13. private
  14.    procedure SetSomeArr(index: Integer; AValue: TSomeRecord );
  15.    function GetSomeArr(index: Integer): TSomeRecord ;
  16.  
  17. public
  18.    property SomeArr [index: Integer]: TSomeRecord read GetSomeArr write SetSomeArr;
  19.    procedure InitData;
  20.    
  21. end;
  22. implementation
  23.  
  24. procedure TAClass.InitData;
  25. begin
  26.    SomeArr[0].S1:= 'test';
  27.    SomeArr[0].S2:= 'test';
  28.    SomeArr[0].S3:= 'test';
  29. end;
  30.  
  31. function TAClass.GetSomeArr(index: Integer): TSomeRecord;
  32. begin
  33.    if (index < Length(fSomeArr)) and (index >= 0) then begin
  34.       Result:= fSomeArr[index];
  35.    end;
  36. end;
  37.  
  38. procedure TAClass.SetSomeArr(index: Integer; AValue: TSomeRecord);
  39. begin
  40.    if (index < Length(fSomeArr)) and (index >= 0) then begin
  41.       fSomeArr[index].S1:= AValue.S1;
  42.       fSomeArr[index].S2:= AValue.S2;
  43.       fSomeArr[index].S3:= AValue.S3;
  44.    end;
  45.  
  46.    Case index of
  47.       0: ShowMessage('Array Field 1 Changed');
  48.       1: ShowMessage('Array Field 2 Changed')
  49.    end;
  50. end;
  51.  

This Code provides the following Error: "Argument cannot be assigned to"

Quote
   SomeArr[0].S1:= 'test';
   SomeArr[0].S2:= 'test';
   SomeArr[0].S3:= 'test';

how do I change the code to make this work ?

Thanks in advance !
« Last Edit: June 29, 2022, 07:47:09 am by Weitentaaal »
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.2

Weitentaaal

  • Hero Member
  • *****
  • Posts: 503
  • Weitental is a very beautiful garbage depot.
Re: Array of Record as Property
« Reply #1 on: June 28, 2022, 04:04:09 pm »
I solved it in a dirty way:

Code: Pascal  [Select][+][-]
  1.       property SomeArrS1 [index: Integer]: String read GetSomeArrS1 write SetSomeArrS1;
  2.       property SomeArrS2 [index: Integer]: String read GetSomeArrS2 write SetSomeArrS2;
  3.       property SomeArrS3 [index: Integer]: String read GetSomeArrS3 write SetSomeArrS3;
  4.  

any other Solution?, because the number of getter and setter would explode
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.2

jcmontherock

  • Full Member
  • ***
  • Posts: 234
Re: Array of Record as Property
« Reply #2 on: June 28, 2022, 04:28:36 pm »
Two suggestions:
1) Use dynamic arrays. It works with records.
2) Set the length of your strings (ex: string[255]).
Windows 11 UTF8-64 - Lazarus 3.2-64 - FPC 3.2.2

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Re: Array of Record as Property
« Reply #3 on: June 28, 2022, 04:37:37 pm »
This works
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. Uses SysUtils, Classes;
  3.  
  4. Type
  5.   TSomeRecord=Record
  6.     s1:String;
  7.     s2:String;
  8.     s3:String;
  9.   end;
  10.  
  11.   { TAClass }
  12.  
  13.   TAClass = Class
  14.     Private
  15.       fSomeArr:Array[0..1] Of TSomeRecord;
  16.     Protected
  17.       Procedure SetSomeArr(AIndex:Integer;AValue:TSomeRecord);
  18.       Function GetSomeArr(AIndex:Integer):TSomeRecord;
  19.     Public
  20.       Property SomeArr[AIndex:Integer]:TSomeRecord Read GetSomeArr Write SetSomeArr;
  21.       Procedure InitData;
  22.   end;
  23.  
  24. { TAClass }
  25.  
  26. procedure TAClass.SetSomeArr(AIndex: Integer; AValue: TSomeRecord);
  27. begin
  28.   fSomeArr[AIndex].s1:=AValue.s1;
  29.   fSomeArr[AIndex].s2:=AValue.s2;
  30.   fSomeArr[AIndex].s3:=AValue.s3;
  31. end;
  32.  
  33. function TAClass.GetSomeArr(AIndex: Integer): TSomeRecord;
  34. begin
  35.   Result:=fSomeArr[AIndex];
  36. end;
  37.  
  38. procedure TAClass.InitData;
  39. begin
  40.   fSomeArr[0].s1:='Test 1';
  41.   fSomeArr[0].s2:='Test 2';
  42.   fSomeArr[0].s3:='Test 3';
  43.   fSomeArr[1].s1:='empty 1';
  44.   fSomeArr[1].s2:='empty 2';
  45.   fSomeArr[1].s3:='empty 3';
  46. end;
  47.  
  48. Var
  49.   MyClass:TAClass;
  50.   MyArr:TSomeRecord;
  51.   i:Integer;
  52.  
  53. begin
  54.   MyClass:=TAClass.Create;
  55.   MyClass.InitData;
  56.   For i:=0 To 1 Do
  57.     Begin
  58.       Writeln(MyClass.SomeArr[i].s1);
  59.       Writeln(MyClass.SomeArr[i].s2);
  60.       Writeln(MyClass.SomeArr[i].s3);
  61.     End;
  62.   MyArr.s1:='test 11';
  63.   MyArr.s2:='test 12';
  64.   MyArr.s3:='test 13';
  65.   MyClass.SomeArr[1]:=MyArr;
  66.   For i:=0 To 1 Do
  67.     Begin
  68.       Writeln(MyClass.SomeArr[i].s1);
  69.       Writeln(MyClass.SomeArr[i].s2);
  70.       Writeln(MyClass.SomeArr[i].s3);
  71.     End;
  72. end.


Returns
Test 1
Test 2
Test 3
empty 1
empty 2
empty 3
Test 1
Test 2
Test 3
test 11
test 12
test 13
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Weitentaaal

  • Hero Member
  • *****
  • Posts: 503
  • Weitental is a very beautiful garbage depot.
Re: Array of Record as Property
« Reply #4 on: June 28, 2022, 05:18:53 pm »
Two suggestions:
1) Use dynamic arrays. It works with records.
2) Set the length of your strings (ex: string[255]).

tried both, but i couldn't get it to work  %)


This works
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. Uses SysUtils, Classes;
  3.  
  4. Type
  5.   TSomeRecord=Record
  6.     s1:String;
  7.     s2:String;
  8.     s3:String;
  9.   end;
  10.  
  11.   { TAClass }
  12.  
  13.   TAClass = Class
  14.     Private
  15.       fSomeArr:Array[0..1] Of TSomeRecord;
  16.     Protected
  17.       Procedure SetSomeArr(AIndex:Integer;AValue:TSomeRecord);
  18.       Function GetSomeArr(AIndex:Integer):TSomeRecord;
  19.     Public
  20.       Property SomeArr[AIndex:Integer]:TSomeRecord Read GetSomeArr Write SetSomeArr;
  21.       Procedure InitData;
  22.   end;
  23.  
  24. { TAClass }
  25.  
  26. procedure TAClass.SetSomeArr(AIndex: Integer; AValue: TSomeRecord);
  27. begin
  28.   fSomeArr[AIndex].s1:=AValue.s1;
  29.   fSomeArr[AIndex].s2:=AValue.s2;
  30.   fSomeArr[AIndex].s3:=AValue.s3;
  31. end;
  32.  
  33. function TAClass.GetSomeArr(AIndex: Integer): TSomeRecord;
  34. begin
  35.   Result:=fSomeArr[AIndex];
  36. end;
  37.  
  38. procedure TAClass.InitData;
  39. begin
  40.   fSomeArr[0].s1:='Test 1';
  41.   fSomeArr[0].s2:='Test 2';
  42.   fSomeArr[0].s3:='Test 3';
  43.   fSomeArr[1].s1:='empty 1';
  44.   fSomeArr[1].s2:='empty 2';
  45.   fSomeArr[1].s3:='empty 3';
  46. end;
  47.  
  48. Var
  49.   MyClass:TAClass;
  50.   MyArr:TSomeRecord;
  51.   i:Integer;
  52.  
  53. begin
  54.   MyClass:=TAClass.Create;
  55.   MyClass.InitData;
  56.   For i:=0 To 1 Do
  57.     Begin
  58.       Writeln(MyClass.SomeArr[i].s1);
  59.       Writeln(MyClass.SomeArr[i].s2);
  60.       Writeln(MyClass.SomeArr[i].s3);
  61.     End;
  62.   MyArr.s1:='test 11';
  63.   MyArr.s2:='test 12';
  64.   MyArr.s3:='test 13';
  65.   MyClass.SomeArr[1]:=MyArr;
  66.   For i:=0 To 1 Do
  67.     Begin
  68.       Writeln(MyClass.SomeArr[i].s1);
  69.       Writeln(MyClass.SomeArr[i].s2);
  70.       Writeln(MyClass.SomeArr[i].s3);
  71.     End;
  72. end.


Returns
Test 1
Test 2
Test 3
empty 1
empty 2
empty 3
Test 1
Test 2
Test 3
test 11
test 12
test 13

guess i will have to do it this way, just tried to avoid creating a temporery record. Thanks !
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.2

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Array of Record as Property
« Reply #5 on: June 28, 2022, 06:19:36 pm »
how do I change the code to make this work ?

By giving us a complete program to play with, including the bit where you set the compiler mode etc. and telling us what version of FPC you're using.

Sorry to nitpick, but what you're doing /shouldn't/ be a problem...

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: Array of Record as Property
« Reply #6 on: June 28, 2022, 07:36:30 pm »
There is an easy but ugly way and a complicated way, which at the point of usage looks like direct access to the array.

First the easy way, just access it via pointer:
Code: Pascal  [Select][+][-]
  1. type
  2.   PTestRec = ^TTestRec;
  3.   TTestRec = record
  4.     A, B, C: Integer;
  5.   end;
  6.  
  7.   { TTest }
  8.  
  9.   TTest = class
  10.   private
  11.     FData: array of TTestRec;
  12.  
  13.     constructor Create;
  14.     function GetItemPtr(AIndex: Integer): PTestRec;
  15.   public
  16.  
  17.     property ItemPtr[AIndex: Integer]: PTestRec read GetItemPtr;
  18.   end;
  19.  
  20. { TTest }
  21.  
  22. constructor TTest.Create;
  23. begin
  24.   SetLength(FData, 1);
  25.   FillChar(FData[0], SizeOf(TTestRec), #0);
  26. end;
  27.  
  28. function TTest.GetItemPtr(AIndex: Integer): PTestRec;
  29. begin
  30.   Result := @FData[AIndex];
  31. end;
  32.  
  33. var
  34.   Test: TTest;
  35. begin
  36.   Test := TTest.Create;
  37.   Test.ItemPtr[0]^.A := 42;
  38.   Test.ItemPtr[0]^.B := 42;
  39.   Test.ItemPtr[0]^.C := 42;
  40.   WriteLn(Test.FData[0].A);
  41.   ReadLn;            
  42. end.

This circumvents all access control (as you can see no setter), and you need to use the pointer notation ^ (which could be circumvented by using AutoDeref).

The complicated way is to create a temporary reference object:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$ModeSwitch advancedrecords}
  5.  
  6. type
  7.   PTestRec = ^TTestRec;
  8.   TTestRec = record
  9.     A, B, C: Integer;
  10.   end;
  11.  
  12.   { TTestRecRef }
  13.  
  14.   TTestRecRef = record
  15.   private
  16.     function GetA: Integer;
  17.     function GetB: Integer;
  18.     function GetC: Integer;
  19.     procedure SetA(AValue: Integer);
  20.     procedure SetB(AValue: Integer);
  21.     procedure SetC(AValue: Integer);
  22.   public
  23.     Ref: PTestRec;
  24.  
  25.     property A: Integer read GetA write SetA;
  26.     property B: Integer read GetB write SetB;
  27.     property C: Integer read GetC write SetC;
  28.  
  29.     class operator:=(var AData: TTestRec): TTestRecRef;
  30.     class operator:=(AData: TTestRecRef): TTestRec;
  31.   end;
  32.  
  33.   { TTest }
  34.  
  35.   TTest = class
  36.   private
  37.     FData: array of TTestRec;
  38.  
  39.     constructor Create;
  40.     function GetItem(AIndex: Integer): TTestRecRef;
  41.     procedure SetItem(AIndex: Integer; AValue: TTestRecRef);
  42.   public
  43.  
  44.     property Item[AIndex: Integer]: TTestRecRef read GetItem write SetItem;
  45.   end;
  46.  
  47. constructor TTest.Create;
  48. begin
  49.   SetLength(FData, 1);
  50.   FillChar(FData[0], SizeOf(TTestRec), #0);
  51. end;
  52.  
  53. function TTest.GetItem(AIndex: Integer): TTestRecRef;
  54. begin
  55.   Result := FData[AIndex];
  56. end;
  57.  
  58. procedure TTest.SetItem(AIndex: Integer; AValue: TTestRecRef);
  59. begin
  60.   FData[AIndex] := AValue;
  61. end;
  62.  
  63. { TTestRecRef }
  64.  
  65. function TTestRecRef.GetA: Integer;
  66. begin
  67.   Result := Ref^.A;
  68. end;
  69.  
  70. function TTestRecRef.GetB: Integer;
  71. begin
  72.   Result := Ref^.B;
  73. end;
  74.  
  75. function TTestRecRef.GetC: Integer;
  76. begin
  77.   Result := Ref^.C;
  78. end;
  79.  
  80. procedure TTestRecRef.SetA(AValue: Integer);
  81. begin
  82.   Ref^.A := AValue;
  83. end;
  84.  
  85. procedure TTestRecRef.SetB(AValue: Integer);
  86. begin
  87.   Ref^.B := AValue;
  88. end;
  89.  
  90. procedure TTestRecRef.SetC(AValue: Integer);
  91. begin
  92.   Ref^.C := AValue;
  93. end;
  94.  
  95. class operator TTestRecRef.:=(var AData: TTestRec): TTestRecRef;
  96. begin
  97.   Result.Ref:=@AData;
  98. end;
  99.  
  100. class operator TTestRecRef.:=(AData: TTestRecRef): TTestRec;
  101. begin
  102.   Result:=AData.Ref^;
  103. end;
  104.    
  105.  
  106. var
  107.   Test: TTest;
  108. begin
  109.   Test := TTest.Create;
  110.   Test.Item[0].A:=42;
  111.   Test.Item[0].B:=42;
  112.   Test.Item[0].C:=42;
  113.   WriteLn(Test.FData[0].A);
  114.   ReadLn;
  115. end.
  116.  
This also gives you fine grained access control to every bit of the record

Weitentaaal

  • Hero Member
  • *****
  • Posts: 503
  • Weitental is a very beautiful garbage depot.
Re: Array of Record as Property
« Reply #7 on: June 29, 2022, 07:39:25 am »
how do I change the code to make this work ?

By giving us a complete program to play with, including the bit where you set the compiler mode etc. and telling us what version of FPC you're using.

Sorry to nitpick, but what you're doing /shouldn't/ be a problem...

MarkMLl


Attached a small example

Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.2

Weitentaaal

  • Hero Member
  • *****
  • Posts: 503
  • Weitental is a very beautiful garbage depot.
Re: Array of Record as Property
« Reply #8 on: June 29, 2022, 07:46:11 am »
There is an easy but ugly way and a complicated way, which at the point of usage looks like direct access to the array.

First the easy way, just access it via pointer:
Code: Pascal  [Select][+][-]
  1. type
  2.   PTestRec = ^TTestRec;
  3.   TTestRec = record
  4.     A, B, C: Integer;
  5.   end;
  6.  
  7.   { TTest }
  8.  
  9.   TTest = class
  10.   private
  11.     FData: array of TTestRec;
  12.  
  13.     constructor Create;
  14.     function GetItemPtr(AIndex: Integer): PTestRec;
  15.   public
  16.  
  17.     property ItemPtr[AIndex: Integer]: PTestRec read GetItemPtr;
  18.   end;
  19.  
  20. { TTest }
  21.  
  22. constructor TTest.Create;
  23. begin
  24.   SetLength(FData, 1);
  25.   FillChar(FData[0], SizeOf(TTestRec), #0);
  26. end;
  27.  
  28. function TTest.GetItemPtr(AIndex: Integer): PTestRec;
  29. begin
  30.   Result := @FData[AIndex];
  31. end;
  32.  
  33. var
  34.   Test: TTest;
  35. begin
  36.   Test := TTest.Create;
  37.   Test.ItemPtr[0]^.A := 42;
  38.   Test.ItemPtr[0]^.B := 42;
  39.   Test.ItemPtr[0]^.C := 42;
  40.   WriteLn(Test.FData[0].A);
  41.   ReadLn;            
  42. end.

This circumvents all access control (as you can see no setter), and you need to use the pointer notation ^ (which could be circumvented by using AutoDeref).

The complicated way is to create a temporary reference object:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$ModeSwitch advancedrecords}
  5.  
  6. type
  7.   PTestRec = ^TTestRec;
  8.   TTestRec = record
  9.     A, B, C: Integer;
  10.   end;
  11.  
  12.   { TTestRecRef }
  13.  
  14.   TTestRecRef = record
  15.   private
  16.     function GetA: Integer;
  17.     function GetB: Integer;
  18.     function GetC: Integer;
  19.     procedure SetA(AValue: Integer);
  20.     procedure SetB(AValue: Integer);
  21.     procedure SetC(AValue: Integer);
  22.   public
  23.     Ref: PTestRec;
  24.  
  25.     property A: Integer read GetA write SetA;
  26.     property B: Integer read GetB write SetB;
  27.     property C: Integer read GetC write SetC;
  28.  
  29.     class operator:=(var AData: TTestRec): TTestRecRef;
  30.     class operator:=(AData: TTestRecRef): TTestRec;
  31.   end;
  32.  
  33.   { TTest }
  34.  
  35.   TTest = class
  36.   private
  37.     FData: array of TTestRec;
  38.  
  39.     constructor Create;
  40.     function GetItem(AIndex: Integer): TTestRecRef;
  41.     procedure SetItem(AIndex: Integer; AValue: TTestRecRef);
  42.   public
  43.  
  44.     property Item[AIndex: Integer]: TTestRecRef read GetItem write SetItem;
  45.   end;
  46.  
  47. constructor TTest.Create;
  48. begin
  49.   SetLength(FData, 1);
  50.   FillChar(FData[0], SizeOf(TTestRec), #0);
  51. end;
  52.  
  53. function TTest.GetItem(AIndex: Integer): TTestRecRef;
  54. begin
  55.   Result := FData[AIndex];
  56. end;
  57.  
  58. procedure TTest.SetItem(AIndex: Integer; AValue: TTestRecRef);
  59. begin
  60.   FData[AIndex] := AValue;
  61. end;
  62.  
  63. { TTestRecRef }
  64.  
  65. function TTestRecRef.GetA: Integer;
  66. begin
  67.   Result := Ref^.A;
  68. end;
  69.  
  70. function TTestRecRef.GetB: Integer;
  71. begin
  72.   Result := Ref^.B;
  73. end;
  74.  
  75. function TTestRecRef.GetC: Integer;
  76. begin
  77.   Result := Ref^.C;
  78. end;
  79.  
  80. procedure TTestRecRef.SetA(AValue: Integer);
  81. begin
  82.   Ref^.A := AValue;
  83. end;
  84.  
  85. procedure TTestRecRef.SetB(AValue: Integer);
  86. begin
  87.   Ref^.B := AValue;
  88. end;
  89.  
  90. procedure TTestRecRef.SetC(AValue: Integer);
  91. begin
  92.   Ref^.C := AValue;
  93. end;
  94.  
  95. class operator TTestRecRef.:=(var AData: TTestRec): TTestRecRef;
  96. begin
  97.   Result.Ref:=@AData;
  98. end;
  99.  
  100. class operator TTestRecRef.:=(AData: TTestRecRef): TTestRec;
  101. begin
  102.   Result:=AData.Ref^;
  103. end;
  104.    
  105.  
  106. var
  107.   Test: TTest;
  108. begin
  109.   Test := TTest.Create;
  110.   Test.Item[0].A:=42;
  111.   Test.Item[0].B:=42;
  112.   Test.Item[0].C:=42;
  113.   WriteLn(Test.FData[0].A);
  114.   ReadLn;
  115. end.
  116.  
This also gives you fine grained access control to every bit of the record

Thank you, for those examples !

i do like your first Example. i will give t a try !

your second example does look good but how i said earlier, the number of getter and setter will explode.
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.2

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Array of Record as Property
« Reply #9 on: June 29, 2022, 10:23:58 am »
Attached a small example

OK, so the missing link is that it's mode objfpc and you've got H+.

Zvoni's obviously got a neat solution, but TBH I think I'd go for the verbose solution even if it required a great deal of boilerplate code, since that unambiguously avoids shuffling fields around when they're not going to be changed.

In the general case and noting that in your example the elements are of the same type, do you really need to have a record with (named) fields or could this be done with an array with indexed elements?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Weitentaaal

  • Hero Member
  • *****
  • Posts: 503
  • Weitental is a very beautiful garbage depot.
Re: Array of Record as Property
« Reply #10 on: June 29, 2022, 10:41:38 am »
Attached a small example

OK, so the missing link is that it's mode objfpc and you've got H+.

Zvoni's obviously got a neat solution, but TBH I think I'd go for the verbose solution even if it required a great deal of boilerplate code, since that unambiguously avoids shuffling fields around when they're not going to be changed.

In the general case and noting that in your example the elements are of the same type, do you really need to have a record with (named) fields or could this be done with an array with indexed elements?

MarkMLl


yes i need  a record with (named) fields because in my Code its a rcord of Double, String and integer. Didn't thought about this when writing the example code, just wanted to try this.

Thank you i will take one of the various Solution you guys presented me :)

Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.2

Paolo

  • Sr. Member
  • ****
  • Posts: 499
Re: Array of Record as Property
« Reply #11 on: June 29, 2022, 11:10:22 am »
this can help ?

see attached file

Code: Pascal  [Select][+][-]
  1.   StrNum = (S1, S2, S3);    //-- her you can add/remove other elements without change next code
  2.  
  3.   TStrArr = array [StrNum] of string;
  4.  
  5.   TSomeRecord2 = record
  6.     String_ : TStrArr;
  7.   end;
  8.  
  9.  
  10.   { TAClass2 }
  11.  
  12.   TAClass2 = class
  13.   private
  14.     fSomeArr: Array[0..1] of TSomeRecord2;
  15.   private
  16.     function GetSomeArrStr(index: integer; SNum: StrNum): string;
  17.     procedure SetSomeArrStr(index: integer; Snum: StrNum; AValue: string);
  18.     procedure SetSomeArr(index: Integer; AValue: TSomeRecord2);
  19.     function GetSomeArr(index: Integer): TSomeRecord2;
  20.   public
  21.     property SomeArr [index: Integer]: TSomeRecord2 read GetSomeArr write SetSomeArr;
  22.     property SomeArrStr [index1: integer; SNum: StrNum]: string read GetSomeArrStr write SetSomeArrStr; default;
  23.     procedure InitData;
  24.   end;
  25.  
  26. var
  27.   Form1: TForm1;
  28.  
  29. implementation
  30.  
  31. {$R *.lfm}
  32.  
  33. var
  34.   TmpRec : TAClass2;
  35.  
  36. { TForm1 }
  37.  
  38. procedure TForm1.Button1Click(Sender: TObject);
  39. begin
  40.   TmpRec[0,S1]:=Edit1.Text;  //example usage in assignement
  41.   TmpRec[0,S2]:=Edit2.Text;
  42.   TmpRec[0,S3]:=Edit3.Text;
  43. end;
  44.  
  45. procedure TForm1.Button2Click(Sender: TObject);
  46. begin
  47.   Edit4.Text:=TmpRec[0,S1];  //example usage in reading
  48.   Edit5.Text:=TmpRec[0,S2];
  49.   Edit6.Text:=TmpRec[0,S3];
  50. end;
  51.  
  52. { TAClass2 }
  53.  
  54. function TAClass2.GetSomeArrStr(index: integer; SNum: StrNum): string;
  55. begin
  56.   result:=fSomeArr[index].String_[SNum];
  57. end;
  58.  
  59. procedure TAClass2.SetSomeArrStr(index: integer; Snum: StrNum; AValue: string);
  60. begin
  61.   fSomeArr[index].String_[SNum]:=AValue;
  62. end;
  63.  
  64. procedure TAClass2.SetSomeArr(index: Integer; AValue: TSomeRecord2);
  65. begin
  66.   fSomeArr[index]:=AValue;
  67. end;
  68.  
  69. function TAClass2.GetSomeArr(index: Integer): TSomeRecord2;
  70. begin
  71.   Result:=fSomeArr[index];
  72. end;
  73.  
  74. procedure TAClass2.InitData;
  75. begin
  76.   fSomeArr[0].String_[S1]:='test1';
  77.   fSomeArr[0].String_[S2]:='test2';
  78.   fSomeArr[0].String_[S3]:='test3';
  79. end;
  80.  

Weitentaaal

  • Hero Member
  • *****
  • Posts: 503
  • Weitental is a very beautiful garbage depot.
Re: Array of Record as Property
« Reply #12 on: June 29, 2022, 11:29:00 am »
this can help ?

see attached file

Code: Pascal  [Select][+][-]
  1.   StrNum = (S1, S2, S3);    //-- her you can add/remove other elements without change next code
  2.  
  3.   TStrArr = array [StrNum] of string;
  4.  
  5.   TSomeRecord2 = record
  6.     String_ : TStrArr;
  7.   end;
  8.  
  9.  
  10.   { TAClass2 }
  11.  
  12.   TAClass2 = class
  13.   private
  14.     fSomeArr: Array[0..1] of TSomeRecord2;
  15.   private
  16.     function GetSomeArrStr(index: integer; SNum: StrNum): string;
  17.     procedure SetSomeArrStr(index: integer; Snum: StrNum; AValue: string);
  18.     procedure SetSomeArr(index: Integer; AValue: TSomeRecord2);
  19.     function GetSomeArr(index: Integer): TSomeRecord2;
  20.   public
  21.     property SomeArr [index: Integer]: TSomeRecord2 read GetSomeArr write SetSomeArr;
  22.     property SomeArrStr [index1: integer; SNum: StrNum]: string read GetSomeArrStr write SetSomeArrStr; default;
  23.     procedure InitData;
  24.   end;
  25.  
  26. var
  27.   Form1: TForm1;
  28.  
  29. implementation
  30.  
  31. {$R *.lfm}
  32.  
  33. var
  34.   TmpRec : TAClass2;
  35.  
  36. { TForm1 }
  37.  
  38. procedure TForm1.Button1Click(Sender: TObject);
  39. begin
  40.   TmpRec[0,S1]:=Edit1.Text;  //example usage in assignement
  41.   TmpRec[0,S2]:=Edit2.Text;
  42.   TmpRec[0,S3]:=Edit3.Text;
  43. end;
  44.  
  45. procedure TForm1.Button2Click(Sender: TObject);
  46. begin
  47.   Edit4.Text:=TmpRec[0,S1];  //example usage in reading
  48.   Edit5.Text:=TmpRec[0,S2];
  49.   Edit6.Text:=TmpRec[0,S3];
  50. end;
  51.  
  52. { TAClass2 }
  53.  
  54. function TAClass2.GetSomeArrStr(index: integer; SNum: StrNum): string;
  55. begin
  56.   result:=fSomeArr[index].String_[SNum];
  57. end;
  58.  
  59. procedure TAClass2.SetSomeArrStr(index: integer; Snum: StrNum; AValue: string);
  60. begin
  61.   fSomeArr[index].String_[SNum]:=AValue;
  62. end;
  63.  
  64. procedure TAClass2.SetSomeArr(index: Integer; AValue: TSomeRecord2);
  65. begin
  66.   fSomeArr[index]:=AValue;
  67. end;
  68.  
  69. function TAClass2.GetSomeArr(index: Integer): TSomeRecord2;
  70. begin
  71.   Result:=fSomeArr[index];
  72. end;
  73.  
  74. procedure TAClass2.InitData;
  75. begin
  76.   fSomeArr[0].String_[S1]:='test1';
  77.   fSomeArr[0].String_[S2]:='test2';
  78.   fSomeArr[0].String_[S3]:='test3';
  79. end;
  80.  

very creative solution !

Thank you ! i will try this one too.
Lazarus: 2.0.12 x86_64-win64-win32/win64
Compiler Version: 3.2.2

Paolo

  • Sr. Member
  • ****
  • Posts: 499
Re: Array of Record as Property
« Reply #13 on: June 29, 2022, 02:39:38 pm »
this also should work (not in deep tested), see attached code.


Code: Pascal  [Select][+][-]
  1.  
  2.   TSomeRecord = record
  3.     S1, S2, S3 : string;
  4.   end;
  5.  
  6.   { TIntClass }
  7.  
  8.   TIntClass = class
  9.   private
  10.     fSomeRec: TSomeRecord;
  11.     function GetStr(index: integer): string;
  12.     procedure SetStr(index: integer; AValue: string);
  13.   public
  14.     property S1: string Index 1 read GetStr write SetStr;  //<-- property indexing technique, just one get and set for all Sj
  15.     property S2: string Index 2 read GetStr write SetStr;
  16.     property S3: string Index 3 read GetStr write SetStr;
  17.   end;
  18.  
  19.   { TAClass3 }
  20.  
  21.   TAClass3 = class
  22.   private
  23.     fSomeArr: array [0..1] of TIntClass;
  24.   private
  25.     procedure SetSomeArr(index: Integer; AValue: TIntClass);
  26.     function GetSomeArr(index: Integer): TIntClass;
  27.   public
  28.     property SomeArr [index: Integer]: TIntClass read GetSomeArr write SetSomeArr; default;
  29.     procedure InitData;
  30.     constructor Create;
  31.     destructor Destroy; override;
  32.   end;
  33.  
  34. var
  35.   Form1: TForm1;
  36.  
  37. implementation
  38.  
  39. {$R *.lfm}
  40.  
  41. var
  42.   TmpRec : TAClass3;
  43.  
  44. { TIntClass }
  45.  
  46. function TIntClass.GetStr(index: integer): string;
  47. begin
  48.   case index of
  49.     1:result:=fSomeRec.S1;
  50.     2:result:=fSomeRec.S2;
  51.     3:result:=fSomeRec.S3
  52.   end;
  53. end;
  54.  
  55. procedure TIntClass.SetStr(index: integer; AValue: string);
  56. begin
  57.   case index of
  58.     1:fSomeRec.S1:=AValue;
  59.     2:fSomeRec.S2:=AValue;
  60.     3:fSomeRec.S3:=AValue
  61.   end;
  62. end;
  63.  
  64. { TForm1 }
  65.  
  66. procedure TForm1.Button1Click(Sender: TObject);
  67. begin
  68.   case CheckBox1.checked of
  69.     true:begin
  70.       TmpRec[0].S1:=Edit1.Text;
  71.       TmpRec[0].S2:=Edit2.Text;
  72.       TmpRec[0].S3:=Edit3.Text;
  73.     end;
  74.     false:begin
  75.       TmpRec[1].S1:=Edit1.Text+'2';
  76.       TmpRec[1].S2:=Edit2.Text+'2';
  77.       TmpRec[1].S3:=Edit3.Text+'2';
  78.     end;
  79.   end;
  80. end;
  81.  
  82. procedure TForm1.Button2Click(Sender: TObject);
  83. begin
  84.   case CheckBox1.checked of
  85.     true:begin
  86.       Edit4.Text:=TmpRec[0].S1;
  87.       Edit5.Text:=TmpRec[0].S2;
  88.       Edit6.Text:=TmpRec[0].S3;
  89.     end;
  90.     false:begin
  91.       Edit4.Text:=TmpRec[1].S1;
  92.       Edit5.Text:=TmpRec[1].S2;
  93.       Edit6.Text:=TmpRec[1].S3;
  94.     end;
  95.   end;
  96. end;
  97.  
  98. { TAClass3 }
  99.  
  100. procedure TAClass3.SetSomeArr(index: Integer; AValue: TIntClass);
  101. begin
  102.   fSomeArr[index].fSomeRec:=AValue.fSomeRec; //caution here... copy only data
  103. end;
  104.  
  105. function TAClass3.GetSomeArr(index: Integer): TIntClass;
  106. begin
  107.   Result:=fSomeArr[index];
  108. end;
  109.  
  110. procedure TAClass3.InitData;
  111. begin
  112.   fSomeArr[0].S1:='test1';
  113.   fSomeArr[0].S2:='test2';
  114.   fSomeArr[0].S3:='test3';
  115. end;
  116.  
  117. constructor TAClass3.Create;
  118. begin
  119.   inherited Create;
  120.   fSomeArr[0]:=TIntClass.Create;
  121.   fSomeArr[1]:=TIntClass.Create;
  122. end;
  123.  
  124. destructor TAClass3.Destroy;
  125. begin
  126.   fSomeArr[1].Free;
  127.   fSomeArr[0].Free;
  128.   inherited Destroy;
  129. end;
  130.  
  131. initialization
  132.   TmpRec:=TAClass3.Create;
  133. end.
  134.  
  135.  

Here it is allowed to write what (as I understood) you want
Code: Pascal  [Select][+][-]
  1. TmpRec[0].S1:=Edit1.Text;
  2. Edit4.Text:=TmpRec[0].S1;
  3.  

let me know if you will find bugs.


 

TinyPortal © 2005-2018