Recent

Author Topic: [Solved] Objects and classes  (Read 7660 times)

puredeadoblivion

  • Guest
[Solved] Objects and classes
« on: March 19, 2017, 06:15:21 pm »
Hello there,

 I have an array that contains 30 objects of one class (a deck of 30 cards). And have forgotten how to initialize the array to contain these 30 objects(cards). Can someone show me the code required to create the objects in the array(it's probably really simple)!

 And whilst we are on the topic, anyone how to pass an array of objects into a procedure, and sort that by two of their attributes ( one an integer attribute, the other a string attribute)

Thanks
« Last Edit: March 20, 2017, 12:29:05 pm by puredeadoblivion »

Thaddy

  • Hero Member
  • *****
  • Posts: 14377
  • Sensorship about opinions does not belong here.
Re: Objects and classes
« Reply #1 on: March 19, 2017, 07:41:26 pm »
Code: Pascal  [Select][+][-]
  1. program objectarray;
  2. {$mode objfpc}
  3. type
  4.   TCard =class
  5.   end;
  6. var
  7.   a:array[0..29] of TCard;
  8.   c:TCard;
  9. begin
  10.   for c in a do c.create;
  11.   // and of course
  12.   for c in a do c.free;
  13. end.
« Last Edit: March 19, 2017, 07:45:03 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

ASerge

  • Hero Member
  • *****
  • Posts: 2246
Re: Objects and classes
« Reply #2 on: March 19, 2017, 07:53:36 pm »
Code: Pascal  [Select][+][-]
  1.   for c in a do c.create;
Here, the loop won't work. It will call Create as a normal method on an uninitialized object. Change:
Code: Pascal  [Select][+][-]
  1. program objectarray;
  2. {$mode objfpc}
  3. type
  4.   TCard =class
  5.   end;
  6. var
  7.   a:array[0..29] of TCard;
  8.   c:TCard;
  9.   i: Integer;
  10. begin
  11.   for i := Low(a) to High(a) do
  12.     a[i] := TCard.Create;
  13.   // and of course
  14.   for c in a do c.free;
  15. end.


howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Objects and classes
« Reply #3 on: March 19, 2017, 08:02:56 pm »
There are many ways to approach this. Here's one that includes that sorting you want.
Drop a memo on the empty main form of a new Lazarus project, and fill in the code as follows:

Code: Pascal  [Select][+][-]
  1. unit mainArrayOfCards;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   SysUtils, Forms, Controls, StdCtrls, contnrs, strutils, math;
  9.  
  10.  
  11. type
  12.  
  13.   { TCard }
  14.  
  15.   TCard = class(TObject)
  16.   private
  17.     FIntProp: Integer;
  18.     FStrProp: string;
  19.     procedure SetIntProp(aValue: Integer);
  20.     procedure SetStrProp(const aValue: string);
  21.   public
  22.     constructor Create(const aStr: string; anInt: Integer);
  23.     property StrProp: string read FStrProp write SetStrProp;
  24.     property IntProp: Integer read FIntProp write SetIntProp;
  25.   end;
  26.  
  27.   { TDeck }
  28.  
  29.   TDeck = class(TObjectList)
  30.   public
  31.     function AddCard(aCard: TCard): Integer;
  32.     procedure SortByIntThenString;
  33.   end;
  34.  
  35.   { TForm1 }
  36.  
  37.   TForm1 = class(TForm)
  38.     Memo: TMemo;
  39.     procedure FormCreate(Sender: TObject);
  40.     procedure FormDestroy(Sender: TObject);
  41.   private
  42.     FDeck: TDeck;
  43.     procedure CreateDeck;
  44.     procedure WriteDeck;
  45.   public
  46.   end;
  47.  
  48. var
  49.   Form1: TForm1;
  50.  
  51. implementation
  52.  
  53. {$R *.lfm}
  54.  
  55. { TDeck }
  56.  
  57. function IntThenStrCompare(Item1, Item2: Pointer): Integer;
  58. var
  59.   c1: TCard absolute Item1;
  60.   c2: TCard absolute Item2;
  61. begin
  62.   if (c1.FIntProp < c2.FIntProp) then
  63.     Exit(-1)
  64.   else if (c1.FIntProp > c2.FIntProp) then
  65.     Exit(1)
  66.   else Exit(strcomp(PChar(c1.FStrProp), PChar(c2.FStrProp)));
  67. end;
  68.  
  69. { TForm1 }
  70.  
  71. procedure TForm1.CreateDeck;
  72. var
  73.   i: Byte;
  74.   j: Integer;
  75.   s: string;
  76.   intSet: set of byte = [];
  77. begin
  78.   Randomize;
  79.   FDeck:=TDeck.Create(True);
  80.   for j:=1 to 30 do begin
  81.     i:=RandomRange(10, 50);
  82.     Str(i, s);
  83.     if (i in intSet) then
  84.       s:=ReverseString(s);
  85.     Include(intSet, i);
  86.     FDeck.AddCard(TCard.Create(Format('Card ''%s'', int#%d',[s, i]),i));
  87.   end;
  88. end;
  89.  
  90. procedure TForm1.FormCreate(Sender: TObject);
  91. begin
  92.   CreateDeck;
  93.   FDeck.SortByIntThenString;
  94.   Memo.Align:=alClient;
  95.   Memo.Clear;
  96.   Memo.ScrollBars:=ssAutoBoth;
  97.   WriteDeck;
  98. end;
  99.  
  100. procedure TForm1.FormDestroy(Sender: TObject);
  101. begin
  102.   FDeck.Free;
  103. end;
  104.  
  105. procedure TForm1.WriteDeck;
  106. var
  107.   o: Pointer;
  108.   card: TCard absolute o;
  109. begin
  110.   Memo.Lines.Add('Contents of FDeck, sorted');
  111.   for o in FDeck do
  112.     Memo.Lines.Add(card.StrProp);
  113. end;
  114.  
  115. function TDeck.AddCard(aCard: TCard): Integer;
  116. begin
  117.   Assert(Assigned(aCard),'TDeck.AddCard: card is nil');
  118.   Exit(Add(aCard));
  119. end;
  120.  
  121. procedure TDeck.SortByIntThenString;
  122. begin
  123.   Sort(@IntThenStrCompare);
  124. end;
  125.  
  126. { TCard }
  127.  
  128. constructor TCard.Create(const aStr: string; anInt: Integer);
  129. begin
  130.   Assert(aStr<>'','TCard.Create: invalid parameter');
  131.   inherited Create;
  132.   FStrProp:=aStr;
  133.   FIntProp:=anInt;
  134. end;
  135.  
  136. procedure TCard.SetIntProp(aValue: Integer);
  137. begin
  138.   if (FIntProp <> aValue) then begin
  139.     FIntProp:=aValue;
  140.     // other processing here
  141.   end;
  142. end;
  143.  
  144. procedure TCard.SetStrProp(const aValue: string);
  145. begin
  146.   if (FStrProp <> aValue) then begin
  147.     FStrProp:=aValue;
  148.     // other processing here
  149.   end;
  150. end;
  151.  
  152. end.

Thaddy

  • Hero Member
  • *****
  • Posts: 14377
  • Sensorship about opinions does not belong here.
Re: Objects and classes
« Reply #4 on: March 19, 2017, 08:06:45 pm »
Code: Pascal  [Select][+][-]
  1.   for c in a do c.create;
Here, the loop won't work. It will call Create as a normal method on an uninitialized object. Change:
Nonsense again. My code works. Tested.
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: [Half Solved] Objects and classes
« Reply #5 on: March 19, 2017, 08:20:08 pm »
Thaddy, if you change your code to
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}
  4. type
  5.   TCard =class
  6.   end;
  7. var
  8.   a: array[0..29] of TCard;
  9.   c: TCard;
  10. begin
  11.   for c in a do
  12.     c.Create;
  13.   for c in a do
  14.     if Assigned(c) then
  15.       WriteLn('Assigned')
  16.     else WriteLn('nil');
  17.   // and of course
  18.   for c in a do c.free;
  19. end.    

you'll see what ASerge means: what he writes is not nonsense, but the truth.

Handoko

  • Hero Member
  • *****
  • Posts: 5158
  • My goal: build my own game engine using Lazarus
Re: [Half Solved] Objects and classes
« Reply #6 on: March 20, 2017, 04:57:18 am »
And whilst we are on the topic, anyone how to pass an array of objects into a procedure, and sort that by two of their attributes ( one an integer attribute, the other a string attribute)

To pass an array of object (Cards), you need to create a new type (TCards). You can pass all cards using TCards or an item using TCard. Alternatively, you do not need to pass the cards or card if the data is declare on the global scope (MyData), you can access it directly from any procedure.

Code: Pascal  [Select][+][-]
  1. type
  2.  
  3.   TCard = class
  4.   end;
  5.  
  6.   TCards = array[0..29] of TCard;
  7.  
  8. var
  9.   MyCards: TCards;
  10.  
  11. //...
  12.  
  13. procedure ShowAllCards(AllCards: TCards);
  14. begin
  15.   // do something
  16. end;
  17.  
  18. procedure ShowACard(Card: TCard)
  19. begin
  20.   // do something
  21. end;

To sort objects, I recommend you to use TFPList or TFPObjectList:
http://www.freepascal.org/docs-html/rtl/classes/tfplist.html
http://www.freepascal.org/docs-html/fcl/contnrs/tfpobjectlist.html
« Last Edit: March 20, 2017, 05:00:05 am by Handoko »

Thaddy

  • Hero Member
  • *****
  • Posts: 14377
  • Sensorship about opinions does not belong here.
Re: [Half Solved] Objects and classes
« Reply #7 on: March 20, 2017, 09:11:37 am »
Thaddy, if you change your code to
you'll see what ASerge means: what he writes is not nonsense, but the truth.
Assigning to an array element in this way is basically the SAME as assigning to a variable, which just happens to be an array element.If you would add just one method to the TCard class you will find that after the create every single class is instantiated and works. This is simply nonsense. You need 3.0.2 and up for this to work. But 3.0.2 is the default.
Bunch of morons. (seriously, I am not taking anything back. If you think you are an expert, act like an expert. I get fed up with this.)
Code: Pascal  [Select][+][-]
  1. program objectarray;
  2. {$mode objfpc}
  3. {$apptype console}
  4. type
  5.   TCard = class
  6.   public
  7.     procedure printme;
  8.   end;
  9.  
  10.   procedure Tcard.printme;
  11.   begin
  12.     writeln('me',Random(100));
  13.   end;
  14. var
  15.   a:array[0..29] of TCard;
  16.   c:TCard;
  17. begin
  18.   for c in a do c.create;
  19.   for c in a do c.printme;
  20.   // and of course
  21.   for c in a do c.free;
  22.   readln;
  23. end.

Sorry, but this is not the first time that ASerge didn't even test the code. He should shut up or test...

I am doing more than enough to do real testing.
Now. Can you plz explain to me and everybody else why my code works? <grumpy mode again... >:D >:D >


« Last Edit: March 20, 2017, 10:17:49 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: [Half Solved] Objects and classes
« Reply #8 on: March 20, 2017, 10:28:59 am »
Thaddy, I cannot explain why your code works, except that it relies on writeln calling a global procedure and does not actually need to access an instantiated object.
If you make the very slight change to your printme method as below you'll see that no TCards are actually instantiated by your loop construct
Code: Pascal  [Select][+][-]
  1. for c in a do c.create;
.

You only have to modify your your code slightly for it to fail completely.
Code: Pascal  [Select][+][-]
  1. program objectarray;
  2. {$mode objfpc}
  3. {$apptype console}
  4. type
  5.   TCard = class
  6.   public
  7.     procedure printme;
  8.   end;
  9.  
  10.   procedure Tcard.printme;
  11.   begin
  12.    // writeln('me',Random(100));
  13.     WriteLn(Self.ClassName);
  14.   end;
  15. var
  16.   a:array[0..29] of TCard;
  17.   c:TCard;
  18. begin
  19.   for c in a do c.create;
  20.   for c in a do c.printme;
  21.   // and of course
  22.   for c in a do c.free;
  23.   readln;
  24. end.

BTW I am not an expert, and make no claim to be such. However, I see no reason to be browbeaten for simply supporting ASerge's assertion, which as far as I can see is a fact.

sky_khan

  • Guest
Re: [Half Solved] Objects and classes
« Reply #9 on: March 20, 2017, 10:35:55 am »
@Thaddy I wish you were joking but this is enough.

Code: Pascal  [Select][+][-]
  1. program objectarray;
  2. {$mode objfpc}
  3. {$apptype console}
  4.  
  5. uses classes, sysutils;
  6.  
  7. type
  8.   TCardSuit = (sHearts,sDiamonds,sSpades,sClubs);
  9.  
  10.   { TCard }
  11.  
  12.   TCard = class
  13.   private
  14.     FSuit : TCardSuit;
  15.     FFront : Byte;
  16.   public
  17.     function SuitName: string;
  18.     function FrontName: string;
  19.     procedure printme;
  20.   end;
  21.  
  22.   function TCard.SuitName: string;
  23.   begin
  24.     case FSuit of
  25.       sHearts: Result:='Hearts';
  26.       sDiamonds: Result:='Diamonds';
  27.       sSpades: Result:='Spades';
  28.       sClubs: Result:='Clubs';
  29.     end;
  30.   end;
  31.  
  32.   function TCard.FrontName: string;
  33.   begin
  34.     case FFront of
  35.       1: Result:='Ace';
  36.       2..10 : Result:=IntToStr(FFront);
  37.       11 : Result:='Jack';
  38.       12 : Result:='Queen';
  39.       13 : Result:='King';
  40.     end;
  41.   end;
  42.  
  43.   procedure TCard.printme;
  44.   begin
  45.     writeln(Format('self:%p',[pointer(self)]));
  46. //    writeln(Format('I''m %s of %s',[FrontName,SuitName]));
  47.  
  48.     writeln('me',Random(100));
  49.   end;
  50. var
  51.   a:array[0..29] of TCard;
  52.   c:TCard;
  53.  
  54.   i : integer;
  55. begin
  56.   Fillchar(a,sizeof(a),0);
  57.   for c in a do c.create; // calls create on NIL
  58.   for c in a do c.printme; // calls printme on NIL
  59.   // of course both works because you dont use object (self pointer=NIL) at all
  60.   // if still not convinced, uncomment the line which use member variables in "printme"
  61.  
  62.   for i:=low(a) to high(a) do
  63.     writeln(Format('a[%d]=%p',[i,Pointer(a[i])]));
  64.   // Besides, as you see, you're not assigning array slots too, array is untouched here!
  65.   // and of course
  66.   for c in a do c.free;
  67.   readln;
  68. end.
  69.  

You really should think twice before calling names.
« Last Edit: March 20, 2017, 10:39:17 am by SkyKhan »

Thaddy

  • Hero Member
  • *****
  • Posts: 14377
  • Sensorship about opinions does not belong here.
Re: [Solved] Objects and classes
« Reply #10 on: March 20, 2017, 03:07:12 pm »
Ok. I will file a bug report. Either my code should work, which it does!!!!! or not.
Let the compiler guru's decide (I know the answer: assigning to an array element is just as valid as assigning to a single variable)
You merely hit a bug.
« Last Edit: March 20, 2017, 03:10:59 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

kupferstecher

  • Hero Member
  • *****
  • Posts: 583
Re: [Solved] Objects and classes
« Reply #11 on: March 20, 2017, 03:30:04 pm »
Thaddy, I think you miss their point?

Your code is
Code: Pascal  [Select][+][-]
  1. c.create
but should be
Code: Pascal  [Select][+][-]
  1. c:= TCard.Create;

I made this stupid mistake a thousand times... No compiler warning, just a crash when trying to use the instance (In new version different?).

sky_khan

  • Guest
Re: [Solved] Objects and classes
« Reply #12 on: March 20, 2017, 03:36:24 pm »
@Thaddy
Where in any of pascal documents is written that calling a constructor on instance variable should work ?
Do you really think this is valid code ?
Code: Pascal  [Select][+][-]
  1. var
  2.   Strs : TStringList;
  3. begin
  4.   Strs.Create;
  5. end;
  6.  
Because thats what you do with "for c in a do c.create;" WTF ?

This is how you instantiate objects, remember ?
Strs:=TStringList.Create

sky_khan

  • Guest
Re: [Solved] Objects and classes
« Reply #13 on: March 20, 2017, 03:44:44 pm »
@Thaddy
BTW, if you keep insisting you're right and everybody else is wrong you will be my first person on my ignore list.

Thaddy

  • Hero Member
  • *****
  • Posts: 14377
  • Sensorship about opinions does not belong here.
Re: [Solved] Objects and classes
« Reply #14 on: March 20, 2017, 05:14:19 pm »
@Thaddy
BTW, if you keep insisting you're right and everybody else is wrong you will be my first person on my ignore list.
Well... try the code... It works....
« Last Edit: March 20, 2017, 05:27:51 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

 

TinyPortal © 2005-2018