Reputation: 16612
If I write
type
MyClass = class of TMyClass;
...
Obj := MyClass.Create;
the correct constructor (the one in TMyClass) is called.
If I write
var
ClassVar : TClass;
...
ClassVar := TMyClass;
Obj := ClassVar.Create;
only the TObject constructor is called.
Why? What's the difference between the two versions? Can I force the TMyClass constructor call in the second scenario?
Upvotes: 2
Views: 406
Reputation: 3820
Or descend it from TComponent, which already have a virtual constructor.
Upvotes: -3
Reputation: 4415
TObject.Create is not virtual, you need to declare ClassVar as a classtype of a class with a virtual constructor.
Upvotes: 4
Reputation: 36840
I would suggest you look into overriding the AfterConstruction method that's introduced by the TObject to make polymorphism like this work.
Each class definition can introduce a new constructor, with it's own set of parameters. A class variable only knows of the constructor if the base class it's a variable for. This is all possible because a constructor is neither virtual nor overridden. You could flag the constructor virtual on your base-class, and flag all descending classes override, which blocks the parameter list. (I think if you forget 'override' the compiler warns your new constructir hides the virtual one.)
Upvotes: 2
Reputation: 84540
TClass is declared as "Class of TObject
" in system.pas. What constructor gets called is decided at compile-time, and all the compiler knows is what base class you're using. It doesn't know what the value of the variable will be when it runs, so it has to default to the base class. If you're using a TClass, then your base class is TObject.
If you're using a class variable, I assume you have some sort of heirarchy and you're trying to implement a factory. If you want to make sure the right constructor gets called based on the value of a class variable at runtime, not something contained in your code at compile time, you need a virtual constructor.
type
TMyBaseObject = class(TObject)
public
constructor Create; virtual;
end;
TMyClass = class of TMyBaseObject;
Use a TMyClass instead of a TClass as your class variable, and now the compiler will generate a call to TMyBaseObject.Create, which is virtual. Make sure all your derived classes override the base constructor, and you'll end up calling the right one at runtime.
Upvotes: 11