* * *

Author Topic: class var problem?  (Read 1091 times)

apexcol

  • Jr. Member
  • **
  • Posts: 51
class var problem?
« on: December 31, 2017, 05:34:52 am »
I have this...
Code: Pascal  [Select]
  1. TFruit = class
  2.     class var FhowMany: integer;
  3.   private
  4.     class procedure SetHowMany(const aValue: integer); static;
  5.   public
  6.     class constructor create;
  7.     class destructor destroy;
  8.     class property amount: integer read FhowMany write SetHowMany;
  9.   end;    
  10.  
  11. { ... }
  12.  
  13. var
  14.   FruitsBasket: TList;
  15.  
  16.  
  17. class procedure TFruit.SetHowMany(const aValue: integer);
  18. begin
  19.   if FhowMany <> aValue then
  20.     FhowMany := aValue;
  21. end;
  22.  
  23. class constructor TFruit.create;
  24. begin
  25.   inherited;
  26.   inc(FhowMany);
  27. end;
  28.  
  29. class destructor TFruit.destroy;
  30. begin
  31.   dec(FhowMany);
  32.   inherited;
  33. end;
  34.  
  35. var
  36.   i: integer;
  37.   F: TFruit;
  38. begin
  39.   FruitsBasket := TList.Create;
  40.  
  41.   for i:=1 to 10 do
  42.     FruitsBasket(TFruits.Create);
  43.  
  44.   writeln('Fruits: ' + F.amount);
  45. end.
  46.  
Question:  Why printed result is only 1?  it ought to be 10, right?

Kays

  • Jr. Member
  • **
  • Posts: 87
  • Whasup!?
    • KaiBurghardt.de
Re: class var problem?
« Reply #1 on: December 31, 2017, 06:12:08 am »
Uh, the notion constructor/destructors only exist for objects, instances of a class. So a “class constructor”/“class destructor” is kinda wrong.

Maybe, I usually put classes into separate units and utilize the initialization and finalization block in the unit for operation on the class, maybe a “class constructor” behaves like doing stuff in such an initialization section, especially since you're in a program (I see your last line reads end dot).

PS: Writing class and the static modifier is redundant.
PPS: Your class var FHowMany is in the default section, which public, are you aware of that?
Yours Sincerely
Kai Burghardt

Thaddy

  • Hero Member
  • *****
  • Posts: 5798
Re: class var problem?
« Reply #2 on: December 31, 2017, 07:58:38 am »
Uh, the notion constructor/destructors only exist for objects, instances of a class.
Actutally,with trunk this is possible because of management operators. I will add an example;
recommends {$macro on}{$define Silly:=ObjFpc}

molly

  • Hero Member
  • *****
  • Posts: 2345
Re: class var problem?
« Reply #3 on: December 31, 2017, 08:00:38 am »
Uh, the notion constructor/destructors only exist for objects, instances of a class. So a “class constructor”/“class destructor” is kinda wrong.
Uhm... unless i misunderstood your words then no, it is not kinda wrong.

See Delphi documentation:
Quote
A class constructor is a special class method that is not accessible to developers. Calls to class constructors are inserted automatically by the compiler into the initialization section of the unit where the class is defined. Normally, class constructors are used to initialize the static fields of the class or to perform a type of initialization, which is required before the class or any class instance can function properly. Even though the same result can be obtained by placing class initialization code into the initialization section, class constructors have the benefit of helping the compiler decide which classes should be included into the final binary file and which should be removed from it.

I've seen some talk on that subject with regards to Free Pascal but have no idea if this already works for Free Pascal (without any issues)

edit: ah Thaddy beat me to it   ;D

Thaddy

  • Hero Member
  • *****
  • Posts: 5798
Re: class var problem?
« Reply #4 on: December 31, 2017, 09:47:30 am »
I removed the interffaced example, here's another, simpler and cleaner one, more like you first proposed:
Code: Pascal  [Select]
  1. {$ifdef fpc}{$mode delphi}{$H+}{$I-}{$endif}
  2. uses fgl;
  3. type
  4.  
  5. TFruit = class
  6. strict private
  7.   class constructor create; //yes, molly this works
  8. public
  9.   class var Count:Longint;
  10.   constructor create;
  11.   destructor destroy;override;
  12. end;
  13.  
  14. class constructor TFruit.create;
  15. begin
  16.   Count := 0;
  17. end;
  18.  
  19. constructor TFruit.Create;
  20. begin
  21.   inherited;
  22.   inc(Count);
  23. end;
  24.  
  25. destructor TFruit.Destroy;
  26. begin
  27.   dec(Count);
  28.   inherited;
  29. end;
  30.  
  31. var  
  32.   Basket:TFPGObjectlist<TFruit>;
  33.   i:Integer;
  34. begin
  35.   Basket := TFPGObjectList<Tfruit>.Create;
  36.   Basket.FreeObjects := true;
  37.   for i := 0 to 9 do
  38.   begin
  39.     Basket.Add(TFruit.Create);
  40.     writeln(Basket[i].count);
  41.   end;
  42.   Basket.Free;
  43. end.
  44. .

I think this is what you need: not overly complex and very clean code.
« Last Edit: December 31, 2017, 10:31:54 am by Thaddy »
recommends {$macro on}{$define Silly:=ObjFpc}

PascalDragon

  • Jr. Member
  • **
  • Posts: 88
  • Compiler Developer
Re: class var problem?
« Reply #5 on: January 02, 2018, 10:43:02 pm »
Question:  Why printed result is only 1?  it ought to be 10, right?

No, 1 is indeed correct. class constructors and destructors are only called once per type. If you remove the class from the constructor and destructor it will work as Thaddy demonstrated.

hnb

  • Full Member
  • ***
  • Posts: 211
Re: class var problem?
« Reply #6 on: January 02, 2018, 11:12:04 pm »
No, 1 is indeed correct. class constructors and destructors are only called once per type.

I'd like to mention that FPC has critical issue for class var / class constructor / class desctructor combo for generic types ( https://bugs.freepascal.org/view.php?id=28911 ).
Checkout NewPascal initiative and donate beer - ready to use tuned FPC compiler + Lazarus for mORMot project

best regards,
Maciej Izak

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus