Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2025-07

"class of TFoo".Create

8 messages · 5 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Martin Frb

I stumbled (by accident) on (maybe) a curiosity

TFooClass = class of TFoo;
can store a class (that must be TFoo or subclass of it).

I would have expected that the type TFooClass itself is not a class. (Its a container for a class / for lack of better wording)

Yet
TFooClass.Create
compiles. And creates an instance of type TFoo.

Is that intentional.

program Project1;
{$mode objfpc}
type TFoo = class end;
      TFooClass = class of TFoo;
var f: TFoo;
     fc: TFooClass;
begin
   fc := TFoo;
   f  := fc.Create;
   f  := TFooClass.Create;  // works
end.

Reply by email

Bart
to Martin Frb
Show quoted text 11 lines
program Project1; {$mode objfpc} type TFoo = class end; TFooClass = class of TFoo; var f: TFoo; fc: TFooClass; begin fc := TFoo; f := fc.Create; f := TFooClass.Create; // works end.

Delphi (7) happily compiles that as well.
And f is of type TFoo there as well.

Bart

Reply by email

J. Gareth Moreton
to Bart

I would personally call that I would
consider it a type mismatch or a syntax error of some kind, since TFoo is a class and TFooClass is a metaclass.  Also, if I saw such code in a project, I would think someone made a mistake that didn't get caught, since TFoo.Create would make much more sense.

I'd wonder if, under OBJFPC mode, such a construct should raise a compiler error because I honestly can't see a situation where it would be correct and intentional over using the associated class in its place.

Kit

Bart wrote 18 lines
On Sun, Jul 6, 2025 at 1:57 PM Martin Frb via fpc-devel wrote: > program Project1; > {$mode objfpc} > type TFoo = class end; > TFooClass = class of TFoo; > var f: TFoo; > fc: TFooClass; > begin > fc := TFoo; > f := fc.Create; > f := TFooClass.Create; // works > end. Delphi (7) happily compiles that as well. And f is of type TFoo there as well.
This email has been checked for viruses by Avast antivirus software. www.avast.com

Reply by email

Zoë Peterson
to J. Gareth Moreton
I would personally call that unusual at best

What do you two expect this construct to do that you think the current behavior is wrong? It’sobviously correct and expected to me as a fundamental part of Object Pascal’s polymorphism. Constructing an object from a class reference is the entire reason that constructors are virtual. It’s how things like TPicture.Graphic are implemented to create the correct image loading object.

Zoë Peterson
Scooter Software

Reply by email

J. Gareth Moreton
to Zoë Peterson

What I mean is that if you want to instantiate an object of class TFoo, you'd call TFoo.Create, not TFooClass.Create.

If you want to take advantage of Object Pascal's unique polymorphism and instantiate a descendant class of TFoo, you'd call MetaClassVariable.Create rather than TFooClass.Create, where MetaClassVariable is defined somewhere as "var MetaClassVariable: TFooClass;" and then set it accordingly before the instantiation.

To just call TFooClass.Create, and TFooClass is implicitly converted to TFoo, feels a bit 'off' and is asking for trouble, while seeing "TFooClass.Create" in the code would be indictive of a bug in my opinion, since the programmer either meant "TFoo" or a variable of type TFooClass instead of "TFooClass" itself.

Zoë Peterson wrote 12 lines
> I would personally call that unusual at best What do you two expect this construct to do that you think the current behavior is wrong? It’sobviously correct and expected to me as a fundamental part of Object Pascal’s polymorphism. Constructing an object from a class reference is the entire reason that constructors are virtual. It’s how things like TPicture.Graphic are implemented to create the correct image loading object. Zoë Peterson Scooter Software _______________________________________________ fpc-devel maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
This email has been checked for viruses by Avast antivirus software. www.avast.com

Reply by email

Martin Frb
to Zoë Peterson: What do you two expect this construct to do that you think the current behavior is wrong?…
Zoë Peterson wrote
> I would personally call that unusual at best What do you two expect this construct to do that you think the current behavior is wrong? It’sobviously correct and expected to me as a fundamental part of Object Pascal’s polymorphism. Constructing an object from a class reference is the entire reason that constructors are virtual. It’s how things like TPicture.Graphic are implemented to create the correct image loading object.

In the below, calling
  fc.Create;
is ok.

fc is a variable, and its value is a class. (that can be TFoo, or TFooChild)

Calling
  TFooClass.Create
on the otherhand...

TFooClass is not a class. Its a type for a variable that then as value can have a class.

And, it also seems to Statically translate into
  TFooClass.Create == TFoo.Create.

The type TFooClass itself can not be assigned a value. So it is always the same.

To answer your question: I expected it to be an error. But if for cautious reasons that is not going to be, then at least a warning, nothing less

program Project1;
{$mode objfpc}
type TFoo = class end;
      TFooClass = class of TFoo;
var f: TFoo;
     fc: TFooClass;
begin
   fc := TFoo;
   f  := fc.Create;
   f  := TFooClass.Create;  // works
end.

Reply by email

J. Gareth Moreton
to Marco van de Voort

Going by what Martin just said, should this throw a warning, at least if not in Delphi mode?  Or an error?  This "feature" being used is more likely due to a programming bug and I feel that the developer's attention should be drawn to it so it can be replaced with TFoo.Create if that's what they meant, or a metaclass variable.

Kit

Marco van de Voort wrote 13 lines
Op 6-7-2025 om 16:31 schreef J. Gareth Moreton via fpc-devel: > What I mean is that if you want to instantiate an object of class > TFoo, you'd call TFoo.Create, not TFooClass.Create. I also don't see the real value of that "feature", but iirc it was added since Delphi allows it. _______________________________________________ fpc-devel maillist  -  https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
This email has been checked for viruses by Avast antivirus software. www.avast.com

Reply by email