Bookstore

Recent

Author Topic: Ideas for class design needed  (Read 1661 times)

asdf1337

  • New Member
  • *
  • Posts: 16
Re: Ideas for class design needed
« Reply #15 on: February 18, 2020, 07:14:07 pm »
Is there any shortcut for having a class like this (as it's not working with FData.<fields> in property definition)
Code: Pascal  [Select]
  1.   TAccessData = class(TAnotherClass)
  2.   private
  3.     FData: TData;
  4.     FData2: TSomeOtherData;
  5.   published
  6.     property ID: String read FData.FID write FData.FID;
  7.     property Title: String read FData.FTitle write FData.FTitle;
  8.     property TitleId2: String read FData2.FTitle write FData2.FTitle;
  9.   end;
  10.  

without writing a setter/getter function for all of them?

Otherwise I'll end up with code like
Code: Pascal  [Select]
  1.   TAccessData = class(TAnotherClass)
  2.   private
  3.     FData: TData;
  4.     FData2: TSomeOtherData;
  5.  
  6.     function getId: String;
  7.     function getTitle: String;
  8.     function getTitle2: String;
  9.     procedure setId(const input: String);
  10.     procedure setTitle(const input: String);
  11.     procedure setTitle2(const input: String);
  12.   published
  13.     property ID: String read getId write setId;
  14.     property Title: String read getTitle write setTitle;
  15.     property TitleId2: String read getTitle2 write setTitle2;
  16.   end;
  17.  
where each function just looks more or less like this:
Code: Pascal  [Select]
  1. function TAccessData.getId: String;
  2. begin
  3.   Result := FData.ID;
  4. end;
  5.  
  6. procedure TAccessData.setId(const input: String);
  7. begin
  8.   FData.ID := input;
  9. end;
  10. ...
  11. function TAccessData.getTitle2: String;
  12. begin
  13.   Result := FData2.Title;
  14. end;
  15.  
  16. procedure TAccessData.setTitle2(const input: String);
  17. begin
  18.   FData2.Title := input;
  19. end;
  20.  


GetMem

  • Hero Member
  • *****
  • Posts: 3629
Re: Ideas for class design needed
« Reply #16 on: February 18, 2020, 08:16:08 pm »
@asdf1337
Quote
Is there any shortcut for having a class like this (as it's not working with FData.<fields> in property definition)

Use a TObject, like this:
Code: Pascal  [Select]
  1. type
  2.   TData = class(TObject)
  3.     FID: String;
  4.     FTitle: String;
  5.     FTitleId2: String
  6.   end;
  7.  
  8.   TAccessData = class(TAnotherClass)
  9.   private
  10.     FData: TData;
  11.   public
  12.     constructor Create;
  13.     destructor Destroy; override;
  14.   published
  15.     property Data: TData read FData write FData;
  16.   end;
  17.  
  18. implementation
  19.  
  20. constructor TAccessData.Create;
  21. begin
  22.   FData := TData.Create;
  23. end;
  24.  
  25. destructor TAccessData.Destroy;
  26. begin
  27.   FData.Free;
  28.   inherited Destroy;
  29. end;  

asdf1337

  • New Member
  • *
  • Posts: 16
Re: Ideas for class design needed
« Reply #17 on: February 18, 2020, 09:12:13 pm »
@GetMem
That doesn't work in my case. I need to 'export' the properties to maintain compatibility with my other code which is working with these specific properties.
Code: Pascal  [Select]
  1.     property ID: String read getId write setId;
  2.     property Title: String read getTitle write setTitle;
  3.     property TitleId2: String read getTitle2 write setTitle2;
  4.  

Sometimes I've to cast e.g.
Code: Pascal  [Select]
  1. var
  2.   myAccessData: TAccessData;
  3.  
  4.   TSomeOtherData(myAccessData).TitleId2
  5. or
  6.   TData(myAccessData).ID
  7.  
as in some places I'm working only with the TSomeOtherData or TData classes.

ASerge

  • Hero Member
  • *****
  • Posts: 1487
Re: Ideas for class design needed
« Reply #18 on: February 18, 2020, 09:34:12 pm »
without writing a setter/getter function for all of them?
It is possible without getter. For setter use inline and the generated code will be the same as the direct setting of the field.
At least in a small example this is true:
Code: Pascal  [Select]
  1. {$MODE OBJFPC}
  2. {$LONGSTRINGS ON}
  3.  
  4. type
  5.   TSample = class(TObject)
  6.   strict private
  7.     FData: record
  8.       ID: string;
  9.       Title: string;
  10.     end;
  11.     procedure SetId(const AValue: string); inline;
  12.     procedure SetTitle(const AValue: string); inline;
  13.   public
  14.     property ID: string read FData.ID write SetId;
  15.     property Title: string read FData.Title write SetTitle;
  16.   end;
  17.  
  18. procedure TSample.SetId(const AValue: string); inline;
  19. begin
  20.   FData.ID := AValue;
  21. end;
  22.  
  23. procedure TSample.SetTitle(const AValue: string); inline;
  24. begin
  25.   FData.Title := AValue;
  26. end;
  27.  
  28. var
  29.   X: TSample;
  30. begin
  31.   X := TSample.Create;
  32.   try
  33.     X.ID := 'ID or Title';
  34.     X.Title := X.ID;
  35.   finally
  36.     X.Free;
  37.   end;
  38. end.

asdf1337

  • New Member
  • *
  • Posts: 16
Re: Ideas for class design needed
« Reply #19 on: February 18, 2020, 09:55:29 pm »
@ASerge
Does it also work in $mode Delphi? And your using a record where it works with addressing the field directly in the property declaration but according to Martin_fr it doesn't work for classes:
As for the properties, you will need getter methods. The field forwarding only works for records (as they can not be nil, but classes/objects can be nil and the forward would fail).

ASerge

  • Hero Member
  • *****
  • Posts: 1487
Re: Ideas for class design needed
« Reply #20 on: February 19, 2020, 05:07:19 pm »
@ASerge
Does it also work in $mode Delphi? And your using a record where it works with addressing the field directly in the property declaration but according to Martin_fr it doesn't work for classes:
This is a working example, you can easily check. In Delphi mode, too.

Thaddy

  • Hero Member
  • *****
  • Posts: 9782
Re: Ideas for class design needed
« Reply #21 on: February 19, 2020, 05:53:22 pm »
Furthermore, in Delphi proper too....
I am more like donkey than shrek

asdf1337

  • New Member
  • *
  • Posts: 16
Re: Ideas for class design needed
« Reply #22 on: February 19, 2020, 09:50:03 pm »
But as I wrote I've classes and not records. So it doesn't help me that it's working like this with records... That's what Martin_fr already pointed out.
I'm just searching for a more elegant way to solve the problem with properties without writing a bunch of super simple setter/getter functions.

lucamar

  • Hero Member
  • *****
  • Posts: 2566
Re: Ideas for class design needed
« Reply #23 on: February 19, 2020, 10:28:03 pm »
Note that you can set/get several properties wih a single setter+getter pair by adding an index to your properties; only drawback is that all the properties must have the same type. For example:

Code: Pascal  [Select]
  1.   TAccessData = class(TAnotherClass)
  2.   private
  3.     FData: TData;
  4.     function GetField(Index : Integer): String;  
  5.     Procedure SetField(Index: Integer; Value: String);  
  6.   published
  7.     property ID: String index 1 read GetField write SetField;
  8.     property Title: String  index 2 read GetField write SetField;
  9.   end;
  10.  
  11. { later, in the implementation: }
  12.  
  13. function TAccessData.GetField(Index : Integer): String;
  14. begin
  15.   case Index of
  16.   1: Result := FData.FID;
  17.   2: Result := FData.FTitle;
  18.   end;
  19. end;
  20.  
  21. Procedure TAccessData.SetField(Index: Integer; Value: String);  
  22. begin
  23.   case Index of
  24.   1: FData.FID := Value;
  25.   2: FData.FTitle := Value;
  26.   end;
  27. end;

It has the small advantage that if you later add more fields (of the same type) you have only a few, sensible places to modify. And IMHO it's more elegant than not ;)
« Last Edit: February 19, 2020, 10:32:26 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.