How to use a method of an object stored in a TList?
Asked Answered
A

2

6

My question is pretty simple. I have a TList (called queue) containing objects of class CNotif and want to use the method is_alive on those objects.

The problem is, when I use queue.Items[0].is_alive(), I get an error message saying Error: Illegal qualifier.

I'm also confused with the way I can instantiate objects in this TList (and how the way the compiler "knows" that the objects stored are of this type ...)

What I do now is: queue.Add(CNotif.create(timer, title, text, badge)) but I don't think it's supposed to be done that way.

Thank you in advance !

Auscultate answered 15/4, 2012 at 16:51 Comment(4)
Just a sidenote. There is an unwritten convention to name the types with the first char T, like TLama is type of Lama, so for your case it would be TCNotif ;-)Baeyer
Isn't it C for Classes and T for "basic" types (like an array or a record) ?Auscultate
Nope, it's for all Types, including classes, records, enumerations etc. Let's say for everything you have in the type section of your code.Baeyer
Just to clarify, as TLama points out, in your case it would actually be TNotif if I'm not mistaken - if the C was your prefix intended. But everything after the T is all up to you anyway, so technically there's no right or wrong way to name types. Things will still work without the T but in Delphi, types are expected to begin with T.Appose
S
10

The problem is, when I use queue.Items[0].is_alive(), I get an error message saying Error: Illegal qualifier.

That's because the compiler has no idea what queue.items[0] is other than a generic pointer (see below).

What I do now is: queue.Add(CNotif.create(timer, title, text, badge)) but I don't think it's supposed to be done that way.

This is exactly the way you need to do it. CNotif.Create constructs a new object, and that object descends from TObject. It compiles fine because your queue.Add call is expecting a pointer, and a Delphi/FreePascal variable containing an object instance is actually a pointer. (Both languages hide the need to dereference using MyObj^ for us.)

To use something in queue.Items, you need to tell the compiler what's in there other than a generic pointer (which of course doesn't have an is_alive method). You do that by typecasting:

CNotif(queue.Items[0]).is_alive

Note: There's a shorter way to use the TList.Items; Items is declared as the default property for the TList, so you can omit it:

queue[0] 

is the same as

queue.Items[0]

and is much easier to type.

Sauer answered 15/4, 2012 at 17:5 Comment(2)
Good point. :) My mistake; wrote too quickly and must have been thinking TObjectList. I'll correct it. Thanks. :)Sauer
Indeed, great explanation, +1Appose
E
6

Unless you're stuck with an old Delphi version, you should look into generics.

In the generics.collection unit there is a TList<T> class that you could use here.

Queue:TList<CNotify>;

...
Begin
  Queue := TList<CNotify>.Create; // remember to clean it up
  Queue.Add(CNotify.Create(...));
  Queue.Add(CNotify.Create(...));

  If Queue[0].isAlive then
    Beep;
End;

I haven't used fpc and lazarus for a while, but in Delphi this is definitely the way to do this. Lists of untyped pointers and type-casts all over the place can become a nightmare to maintain.

Energetic answered 15/4, 2012 at 23:55 Comment(2)
+1, but it might be good to mention from D2010+ because there were several problems in D2009 especially with TList.Baeyer
In fpc ObjFPC mode, the syntax is type TQueue = specialize TFPGList<CNotify> -- but you can also use Delphi mode which has Delphi syntax (at least since 2.6).Interaction

© 2022 - 2024 — McMap. All rights reserved.