Recent

Author Topic: Creating Array Of Objects  (Read 2976 times)

nikel

  • Full Member
  • ***
  • Posts: 218
Creating Array Of Objects
« on: May 21, 2024, 03:37:44 pm »
Hello, I'm trying to create array of objects. I have TMain, TEntireSongs and TSong classes. Here's my code

Code: Pascal  [Select][+][-]
  1. unit EntireSongsHandler;
  2.  
  3. {$mode ObjFPC}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils,
  9.   Config, Token;
  10.  
  11. type
  12.   TEntireSongs = object
  13.   private
  14.     List      : TStringList;
  15.     FArrSongs : array[0..200, 1..12] of string;
  16.     Token     : PToken;
  17.   public
  18.     constructor Init;
  19.     destructor Done;
  20.  
  21.     function GetSongByIndex(Num: Integer): TSong;
  22.     ...

... and TSong class

Code: Pascal  [Select][+][-]
  1. unit songhandler;
  2.  
  3. {$mode ObjFPC}{$H+}
  4. {$TYPEDADDRESS ON}
  5.  
  6. interface
  7.  
  8. uses
  9.   Classes, SysUtils,
  10.   Token, Config, HistoryHandler;
  11.  
  12. type
  13.   TSong = object(TEntireSongs)
  14.   private
  15.     FID        : Integer;
  16.     FEnabled   : Boolean;
  17.     FPlayCount : Integer;
  18.     FAlbum     : string;
  19.     FArtist    : string;
  20.     FTitle     : string;
  21.     FDuration  : Integer;
  22.     FBpm       : Integer;
  23.     FKey       : shortstring;
  24.     FDate      : shortstring;
  25.     FPriority  : Byte;
  26.     FPath      : string;
  27.   public
  28.     property ID          : Integer read FID write FID;
  29.     ...

I'm getting error
Quote
entiresongshandler.pas(21,50) Error: Identifier not found "TSong"

I tried TEntireSongs = array[0..200, 1..12] of string; but didn't work.

How can I fix errors?

WooBean

  • Sr. Member
  • ****
  • Posts: 277
Re: Creating Array Of Objects
« Reply #1 on: May 21, 2024, 03:48:52 pm »
Hello, I'm trying to create array of objects. I have TMain, TEntireSongs and TSong classes. Here's my code

Code: Pascal  [Select][+][-]
  1. unit EntireSongsHandler;
  2.  
  3. {$mode ObjFPC}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils,
  9.   Config, Token, songhandler; //<- here add
  10. type
  11.   TEntireSongs = object
  12.   private
  13.     List      : TStringList;
  14.     FArrSongs : array[0..200, 1..12] of string;
  15.     Token     : PToken;
  16.   public
  17.     constructor Init;
  18.     destructor Done;
  19.  
  20.     function GetSongByIndex(Num: Integer): TSong;
  21.     ...

...
How can I fix errors?

But this will lead to circular unit reference so put both units in one.
« Last Edit: May 21, 2024, 03:53:29 pm by WooBean »
Platforms: Win7/64, Linux Mint Ulyssa/64

nikel

  • Full Member
  • ***
  • Posts: 218
Re: Creating Array Of Objects
« Reply #2 on: May 21, 2024, 04:06:19 pm »
Thanks for the quick reply. I tried using one file but got the same error. Here's my code so far

Code: Pascal  [Select][+][-]
  1. unit EntireSongsHandler;
  2.  
  3. {$mode ObjFPC}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils,
  9.   Config, Token;
  10.  
  11. type
  12.   TEntireSongs = object
  13.   private
  14.     List      : TStringList;
  15.     FArrSongs : array[0..200, 1..12] of string;
  16.     Token     : PToken;
  17.   public
  18.     constructor Init;
  19.     destructor Done;
  20.  
  21.     function GetSongByIndex(Num: Integer): TSong;
  22.     function GetSongByPath(P: string): TSong;
  23.  
  24.     property ArrSongs : array[0..200, 1..12] of string read FArrSongs write FArrSongs;
  25.   end;
  26.  
  27.   TSong = object(TEntireSongs)
  28.   private
  29.     FID        : Integer;
  30.     FEnabled   : Boolean;
  31.     FPlayCount : Integer;
  32.     FAlbum     : string;
  33.     FArtist    : string;
  34.     FTitle     : string;
  35.     FDuration  : Integer;
  36.     FBpm       : Integer;
  37.     FKey       : shortstring;
  38.     FDate      : shortstring;
  39.     FPriority  : Byte;
  40.     FPath      : string;
  41.   public
  42.     property ID          : Integer read FID write FID;
  43.     ...

Modify:

Code: Pascal  [Select][+][-]
  1. unit EntireSongsHandler;
  2.  
  3. {$mode ObjFPC}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils,
  9.   Config, Token, SongHandler;
  10.  
  11. type
  12.   TEntireSongs = object
  13.   private
  14.     List      : TStringList;
  15.     FArrSongs : array[0..200, 1..12] of string;
  16.     Token     : PToken;
  17.   public
  18.     constructor Init;
  19.     destructor Done;
  20.  
  21.     function GetSongByIndex(Num: Integer): TSong;
  22.     function GetSongByPath(P: string): TSong;
  23.  
  24.     property ArrSongs : array[0..200, 1..12] of string read FArrSongs write FArrSongs;
  25.   end;
  26.  
  27.   TSong = object(TEntireSongs)
  28.   private
  29.     FID        : Integer;
  30.     ...

This gives me error:

Quote
entiresongshandler.pas(21,44) Error: Identifier not found "TSong"

« Last Edit: May 21, 2024, 05:07:02 pm by nikel »

WooBean

  • Sr. Member
  • ****
  • Posts: 277
Re: Creating Array Of Objects
« Reply #3 on: May 21, 2024, 04:27:20 pm »
If you want to have access to unit EntireSongsHandler from (still existing) unit songhandler you need to add them (EntireSongsHandler) in uses clause of songhandler unit.

It may be used in implementation part (all depends on how all application is designed).







Platforms: Win7/64, Linux Mint Ulyssa/64

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10553
  • Debugger - SynEdit - and more
    • wiki
Re: Creating Array Of Objects
« Reply #4 on: May 21, 2024, 07:53:52 pm »
You can't have circular references between "object". Unless you use pointers. Though maybe you meant to use classes, which can have such circles?

"object" in that aspect acts like "record"

You have
Code: Pascal  [Select][+][-]
  1. type
  2.   TEntireSongs = object
  3.   private
  4. ...
  5.      function GetSongByIndex(Num: Integer): TSong; // FORWARD REFERENCE NOT POSSIBLE
  6.   end;
  7.  
  8.  TSong = object(TEntireSongs)  // SINCE IT IS BASED ON TEntireSongs, IT CANNOT MOVE BEFORE TSong
  9. ...
  10.   end;
  11.  




Is there a reason why you use "object" and not "class" ? (Mind "class" needs changes to the code, such as proper creation of instances).

Because with class you can do that. You can forward define "TSong = class" and then later define the details of TSong.



With object you can only forward define pointers to it

Code: Pascal  [Select][+][-]
  1. type
  2.   PSong = ^TSong;  // pointer to TSong, and in this case TSong can be defined later
  3.  
  4.   TEntireSongs = object
  5.   private
  6. ...
  7.      function GetSongByIndex(Num: Integer): PSong; // returns pointer
  8.   end;
  9.  
  10.  TSong = object(TEntireSongs)
  11. ...
  12.   end;
  13.  


Thaddy

  • Hero Member
  • *****
  • Posts: 16196
  • Censorship about opinions does not belong here.
Re: Creating Array Of Objects
« Reply #5 on: May 22, 2024, 08:40:06 am »
It looks like basically a song collection.
Here is how to handle that with the classes unit. I will add an example with the objects unit later, in the case that you prefer objects over classes.
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$apptype console}
  2. uses
  3.   classes;
  4. type
  5.  
  6.   { TSong }
  7.  
  8.   TSong = class(TCollectionItem)
  9.   private
  10.     FName:string;
  11.     FArtist:string;
  12.     FAlbum:string;
  13.     FLength: integer;
  14.   public
  15.     constructor Create(ACollection: TCollection); override;
  16.   published
  17.     //handled through TCollectionItem.ID
  18.     //property ID:Integer read FID write FID;
  19.     property Name:string read Fname write FName;
  20.     property Artist:string read FArtist write FArtist;
  21.     property Album:string  read FAlbum write FAlbum;
  22.     property Length: integer read FLength write FLength;
  23.   end;
  24.  
  25.   { TSongCollection }
  26.  
  27.   TSongCollection = class(TCollection)
  28.   private
  29.     function GetItems(Index: integer): TSong;
  30.     procedure SetItems(Index: integer; AValue: TSong);
  31.   public
  32.     constructor Create;
  33.   public
  34.     function Add: TSong;
  35.     property Items[Index: integer]: TSong read GetItems write SetItems; default;
  36.   end;
  37.  
  38.  
  39. constructor TSong.Create(ACollection: TCollection);
  40. begin
  41.   if Assigned(ACollection) then
  42.     inherited Create(ACollection);
  43. end;
  44.  
  45. { TSongCollection }
  46.  
  47. function TSongCollection.GetItems(Index: integer): TSong;
  48. begin
  49.   Result := TSong(inherited Items[Index]);
  50. end;
  51.  
  52. procedure TSongCollection.SetItems(Index: integer; AValue: TSong);
  53. begin
  54.   Items[Index].Assign(AValue);
  55. end;
  56.  
  57. constructor TSongCollection.Create;
  58. begin
  59.   inherited Create(TSong);
  60. end;
  61.  
  62. function TSongCollection.Add: TSong;
  63. begin
  64.   Result := inherited Add as TSong;
  65. end;
  66.  
  67. var
  68.   Songs: TSongCollection;
  69.   NewSong:TSong;
  70.   i:integer;
  71. begin
  72.   Songs := TSongCollection.Create;
  73.   NewSong := Songs.Add;
  74.   NewSong.Name := 'Jumping Jack Flash';
  75.   NewSong.Artist:= 'The Rolling Stones';
  76.   NewSong.Album := 'The Rolling Stones Rock and Roll Circus';
  77.   NewSong.Length := 100;
  78.   for TCollectionItem(NewSong) in Songs do
  79.     begin
  80.      writeln(Newsong.name);
  81.      writeln(NewSong.ID);
  82.     end;
  83.   Songs.Free;
  84.   readln;
  85. end.
If I smell bad code it usually is bad code and that includes my own code.

Thaddy

  • Hero Member
  • *****
  • Posts: 16196
  • Censorship about opinions does not belong here.
Re: Creating Array Of Objects
« Reply #6 on: May 22, 2024, 01:05:49 pm »
And here is one that uses the objects unit instead:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$apptype console}
  2. uses
  3.   objects;
  4. type
  5.  
  6.   { TSong }
  7.   PSong = ^TSong;
  8.   TSong = object
  9.   private
  10.     FName,
  11.     FArtist,
  12.     FAlbum:string;
  13.   public
  14.     constructor Init(aName,aArtist,aAlbum:string);
  15.     destructor done; virtual;
  16.     property Name  :string read Fname write FName;
  17.     property Artist:string read FArtist write FArtist;
  18.     property Album :string read FAlbum write FAlbum;
  19.   end;
  20.  
  21.  
  22.   { TSongCollection }
  23.   PSongCollection = ^TSongCollection;
  24.   TSongCollection = object(TCollection)
  25.   private
  26.     function GetItems(Index: integer): TSong;virtual;
  27.     procedure SetItems(Index: integer; AValue: TSong);virtual;
  28.   public
  29.     destructor Done;virtual;
  30.     property Items[Index: integer]: TSong read GetItems write SetItems; default;
  31.   end;
  32.  
  33. constructor TSong.Init(aName, aArtist, aAlbum: string);
  34. begin
  35.   Name := aName;
  36.   Artist:= aArtist;
  37.   Album := aAlbum;
  38. end;
  39.  
  40. destructor Tsong.Done;
  41. begin
  42.   //inherited done;
  43. end;
  44.  
  45. { TSongCollection }
  46.  
  47. function TSongCollection.GetItems(Index: integer): TSong;
  48. begin
  49.   Result := TSong(At(Index)^);
  50. end;
  51.  
  52. procedure TSongCollection.SetItems(Index: integer; AValue: TSong);
  53. begin
  54.    inherited Insert(PSong(@AValue));
  55. end;
  56.  
  57. destructor TSongCollection.Done;
  58. begin
  59.    DeleteAll;
  60.    Inherited Done;
  61. end;
  62.  
  63.  
  64. var
  65.   Songs: PSongCollection;
  66.   Song : PSong;
  67.   i:integer;
  68. begin
  69.   { Songs collection with initial capacity of 50 and grow factor 10 }
  70.   New(Songs, init(50,10));
  71.   New(Song,Init('Jumping Jack Flash',
  72.                    'The Rolling Stones',
  73.                    'The Rolling Stones Rock and Roll Circus'));
  74.   Songs^.Insert(Song);
  75.   New(Song,Init('It''s Only Rock ''n Roll (But I Like It)',
  76.                    'The Rolling Stones',
  77.                    'It''s Only Rock ''n Roll'));
  78.   Songs^.Insert(Song);
  79.   writeln(songs^.count);
  80.   writeln(Songs^.Items[0].name);
  81.   writeln(Songs^.Items[0].Artist);
  82.   writeln(Songs^.Items[0].Album);
  83.   writeln;
  84.   writeln(Songs^.Items[1].name);
  85.   writeln(Songs^.Items[1].Artist);
  86.   writeln(Songs^.Items[1].Album);
  87.   Dispose(Song, done);
  88.   Dispose(Songs,done);
  89.   readln;
  90. end.
Example inspired by the TCollection example in the Turbo Vision 2.0 programming guide, 1992.
This is available from the internet archive, but I also have it in print.

Better not mix the objects.TCollection with classes.TCollection etc: They are very very different.
« Last Edit: May 22, 2024, 01:49:30 pm by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

nikel

  • Full Member
  • ***
  • Posts: 218
Re: Creating Array Of Objects
« Reply #7 on: May 22, 2024, 06:18:25 pm »
Thanks for the replies. I'm working on Thaddy's first example.

Thaddy

  • Hero Member
  • *****
  • Posts: 16196
  • Censorship about opinions does not belong here.
Re: Creating Array Of Objects
« Reply #8 on: May 22, 2024, 06:52:22 pm »
@nikel
I will show you how to load/save the collection for both examples tomorrow.
If I smell bad code it usually is bad code and that includes my own code.

 

TinyPortal © 2005-2018