Recent

Author Topic: TList.Count count/capacity changed  (Read 3168 times)

Zaher

  • Hero Member
  • *****
  • Posts: 679
    • parmaja.org
TList.Count count/capacity changed
« on: August 22, 2020, 11:22:09 pm »
I derived TObjectList, when set count of this list (using TObjectList.Count or TList.Count) i want create all objects in new elements.

We don't have capacity changed, or at least SetCount not virtual to get notified count is changed.

lnAdded not triggered when count changed in this method

procedure Notify(Ptr: Pointer; Action: TListNotification); virtual;

Did I missed something to do it?  any idea?

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: TList.Count count/capacity changed
« Reply #1 on: August 22, 2020, 11:49:39 pm »
Hard to say, did you override  the SetCount and if so, did you call the inherited or at some point while in the new SetCount ?
The only true wisdom is knowing you know nothing

Zaher

  • Hero Member
  • *****
  • Posts: 679
    • parmaja.org
Re: TList.Count count/capacity changed
« Reply #2 on: August 23, 2020, 12:04:54 am »
SetCount is not virtual to override it

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: TList.Count count/capacity changed
« Reply #3 on: August 23, 2020, 12:11:30 am »
When I look to code, Notify with lnAdded seems to be triggered only when you use methods Add or Insert.
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: TList.Count count/capacity changed
« Reply #4 on: August 23, 2020, 12:26:45 am »
SetCount is not virtual to override it
Inentroduce SetSize and then call the original via a cast to the base object Tlist(Self).SetCount;

I believe that should work.
 
At the entrance point you can call the Notify to generate the trigger... I assume that is.
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: TList.Count count/capacity changed
« Reply #5 on: August 23, 2020, 12:49:58 am »
Not sure exactly how that interface is suppose to work..

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.   TMyObject = class(TList)
  12.     Private
  13.     Procedure SetCount(ACount:Integer);
  14.     Public
  15.     Property Count:Integer Read GetCount Write SetCount;
  16.   end;
  17.  
  18.   { TForm1 }
  19.  
  20.   TForm1 = class(TForm)
  21.     Button1: TButton;
  22.     procedure Button1Click(Sender: TObject);
  23.     procedure FormCreate(Sender: TObject);
  24.   private
  25.  
  26.   public
  27.  
  28.   end;
  29.  
  30. var
  31.   Form1: TForm1;
  32.   L:TMyObject;
  33.  
  34.  
  35. implementation
  36.  
  37. {$R *.lfm}
  38.  
  39. { TForm1 }
  40.  
  41. procedure TForm1.FormCreate(Sender: TObject);
  42. begin
  43.   L:= TMyObject.Create;
  44. end;
  45.  
  46. procedure TForm1.Button1Click(Sender: TObject);
  47. begin
  48.   L.Count := 10;
  49. end;
  50.  
  51. Procedure TMyObject.SetCount(ACount:Integer);
  52. Begin
  53.   TList(Self).Count := ACount;
  54.   FPONotifyObservers(Self,OOChange,Nil);
  55. end;
  56.  
  57. end.
  58.  
  59.  
Example of overriding a non virtual method
in this case a property.
The only true wisdom is knowing you know nothing

Zaher

  • Hero Member
  • *****
  • Posts: 679
    • parmaja.org
Re: TList.Count count/capacity changed
« Reply #6 on: August 23, 2020, 01:55:15 am »
But if that Object passed as TList parameter to function, this function cant see the derived SetCount

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: TList.Count count/capacity changed
« Reply #7 on: August 23, 2020, 12:48:08 pm »
Please try it.
The most recent count property gets seen first which will call the most recent count setter.

From that method you can call the original property which calls the original setter and the you can do additional steps while in that method like calling the notifier.

This is old style hacking 😀
The only true wisdom is knowing you know nothing

ASerge

  • Hero Member
  • *****
  • Posts: 2223
Re: TList.Count count/capacity changed
« Reply #8 on: August 23, 2020, 02:15:13 pm »
The most recent count property gets seen first which will call the most recent count setter.
This is old style hacking 😀
;D This, of course, is incorrect. Properties are not virtual functions, but simply call the methods specified in the read and write modifiers. If TList specifies a non-virtual SetCount method for the Count property, this method will be called, not the overridden SetCount.

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: TList.Count count/capacity changed
« Reply #9 on: August 23, 2020, 03:06:41 pm »
I beg to differ, I've tested it and the Newest one gets called..

Its a simple matter of dropping the break point on that code and watching it.

I do this a lot in code , it has been working fine for years!

Of course this was done using 3.0.4, and I assume like many around here you could be using 3.2 or higher so if that has changed then shame on the DEVS because it will break lots of code..

 Non virtual methods can be called in this manner, you may get a warning from the compiler about the ancestor being hidden but that is taken care of by calling the ancestor via the cast.

  Code as you wish. You either do something that works or just sit there with a stagnated app because others tell you that you shouldn't be doing that.

 Its your choice really, I choose to do it this way as I have done for some time now.




The only true wisdom is knowing you know nothing

Zaher

  • Hero Member
  • *****
  • Posts: 679
    • parmaja.org
Re: TList.Count count/capacity changed
« Reply #10 on: August 23, 2020, 03:20:25 pm »
@jamie no SetCount not called in 3.0 or 3.2

look at my example

Code: Pascal  [Select][+][-]
  1.   { TmyList }
  2.  
  3.   TmyList = Class(TList)
  4.   protected
  5.     procedure SetCount(NewCount: Integer);
  6.   public
  7.     property Count: Integer read GetCount write SetCount;
  8.   end;
  9.  
  10. { TmyList }
  11.  
  12. procedure TmyList.SetCount(NewCount: Integer);
  13. begin
  14.   inherited;
  15.   //Log it
  16. end;
  17.  
  18. procedure ListSetCount(AList: TList); //notice here it is TList not myList
  19. begin
  20.   AList.Count := 10; //This Line not call the new setcount
  21. end;
  22.  
  23. procedure TForm1.Button1Click(Sender: TObject);
  24. var
  25.   myList: TmyList;
  26. begin
  27.   myList := TmyList.Create;
  28.   //myList.Count := 10; //it call new SetCount
  29.   ListSetCount(myList);
  30. end;
  31.  

ListSetCount function use TList, now setting count there not call it, because SetCount not virtual and we can not override it

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: TList.Count count/capacity changed
« Reply #11 on: August 23, 2020, 03:23:45 pm »
I beg to differ, I've tested it and the Newest one gets called..

It depends on how you address the property. Take a look at the following:

Code: Pascal  [Select][+][-]
  1. {$mode objfpc}
  2.  
  3. type
  4.   TTest = class
  5.   private
  6.     fTest: LongInt;
  7.   public
  8.     property Test: LongInt read fTest;
  9.   end;
  10.  
  11.   TTest2 = class(TTest)
  12.   private
  13.     fTest2: LongInt;
  14.   public
  15.     property Test: LongInt read fTest2;
  16.   end;
  17.  
  18. var
  19.   t: TTest;
  20.   t2: TTest2;
  21. begin
  22.   t2 := TTest2.Create;
  23.   t2.fTest := 42;
  24.   t2.fTest2 := 21;
  25.   t := t2;
  26.  
  27.   Writeln(t.Test); // will write 42
  28.   Writeln(t2.Test); // will write 21
  29. end.

So if you address a TObjectList instance using a TList variable then the property definitons of that will be used, because properties themselves are not virtual. Getter and setter methods can be, but not properties themselves.

BrunoK

  • Sr. Member
  • ****
  • Posts: 452
  • Retired programmer
Re: TList.Count count/capacity changed
« Reply #12 on: August 23, 2020, 05:06:10 pm »
@Zaher What do you want to do ?

The following code works perfectly.

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. uses
  4.   ContNrs;
  5.  
  6. type
  7.   { TmyList }
  8.  
  9.   TmyList = class(TObjectList)
  10.   protected
  11.     procedure SetCount(NewCount: integer);
  12.   public
  13.     property Count: integer read GetCount write SetCount;
  14.   end;
  15.  
  16. { TmyList }
  17.  
  18. procedure TmyList.SetCount(NewCount: integer);
  19. begin
  20.   inherited;
  21.   WriteLn('Log it : Count changed to = ', Count);
  22. end;
  23.  
  24. var
  25.   myList: TmyList;
  26. begin
  27.   myList := TmyList.Create;;
  28.   myList.Count := 10;
  29.   myList.Free;
  30.   ReadLn;
  31. end.

Just a pique to the professionals here, it is ridiculous to have an FList in TList because if TList had been defined as TList = class(TFPList, IFPObserved) much of the derived subclasses would directly use parent class methods ... without duplicating them and creating 2 objects for each TList descendants (The instance + a coclass FList : TFPList).



Zaher

  • Hero Member
  • *****
  • Posts: 679
    • parmaja.org
Re: TList.Count count/capacity changed
« Reply #13 on: August 23, 2020, 06:30:47 pm »
I want to pass TmyList to other functions/objects as TList, but when Count changed i want to be notified count is changed.

The easy feature request is to set SetCount as virtual but I prefer to add more notify or new virtual method  CountChanged(...); virtual;


jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: TList.Count count/capacity changed
« Reply #14 on: August 24, 2020, 01:08:13 am »
Ok, so I understand your issue better now..  :)

It would appear there is a little bug in there ..

The SetCount currently when reducing the size will call Delete which in turn does call the notify(…)

However, when setcount increases the size it does not call anything to trigger a notify

This only happens when directly setting the setcount instead of simply adding items to it which does propagate a Notify.

Code: Pascal  [Select][+][-]
  1. procedure TList.SetCount(NewCount: Integer);
  2. begin
  3.   if NewCount < FList.Count then
  4.     while FList.Count > NewCount do
  5.       Delete(FList.Count - 1)     // Delete is part of TLIST which does use Notify.
  6.   else
  7.     FList.SetCount(NewCount); // This calls the FPLIST which does not have Observers etc.
  8. end;                      
  9.  

 As you can see the Notify method does not get called here NewCount is  >  FLIST.COunt..

Etc

 I suppose you could report this and maybe hope it gets fixed
or you could fix this yourself which would require you to recompile the compiler files..

 Thinking of how we can fake this for now... I'll get back to you on that one ;)

The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018