Saturday, October 11, 2003

Class references and virtual constructors

What are some of the things that makes Delphi unique? One thing that Delphi provides is virtual constructors. So how do you make a virtual call to a constructor when, by definition, you don't have an instance? This is accomplished by using a one of the other somewhat unique Delphi constructs, the class reference. A class reference variable holds, not a class instance, but a class type. They also follow the same assignment compatibility rules that a class type variable does.

So what is this good for? What if you didn't know what class to construct at compile-time? Well, class references and virtual constructors to the rescue. So you can now have a hierarchy of classes where you can decide at run-time which classes to construct and use.


type
TComponent = class
constructor Create; virtual;
end;

TComponentClass = class of TComponent;

...

TMyComponent = class(TComponent)
constructor Create; override;
end;

TMyOtherComponent = class(TComponent);
constructor Create; override;
end;

function CreateComponent(AComponentRef: TComponentClass): TComponent;
begin
Result := AComponentRef.Create;
end;

procedure CreateComponents;
var
AComponent: TComponent;
AnotherComponent: TComponent;
begin
AComponent := CreateComponent(TMyComponent);
AnotherComponent := CreateComponent(TMyOtherComponent);
end;


In the above example, the function CreateComponent will create any component that is of type TComponent or any descendant thereof. TComponent is declared to have a virtual constructor. By passing in a specific class reference type into CreateComponent, any component descendant can be created.

Still not convinced? Well this is exactly how the Delphi form designer functions. When you register your components into the IDE, you are passing a class reference. This is then stored internally in a class reference variable associated with a particular tool palette item. When the user selects the palette item and clicks on the surface of the form designer, that class reference is passed into the designer where a component instance is constructed by calling the virtual constructor through that class reference.

There you have it. Hopefully you can see the power and simplicity of using virtual constructors and class references.

3 comments:

  1. Although it looks like a virtual constructor. But the real constructor of TObject atom is static, isn't it?


    IMO, when a class is created, InitInstance() will be called earlier than the code in constructor TObject.Create;


    best regards

    stanleyxu

    ReplyDelete
  2. [...] Bauer (the Chief Scientist at Embarcadero), wrote a short blog article about this topic as well. There is also a SO question about where virtual constructors are being [...]

    ReplyDelete
  3. [...] Bauer (the Chief Scientist at Embarcadero), wrote a short blog article about this topic as well. There is also a SO question about where virtual constructors are being [...]

    ReplyDelete

Please keep your comments related to the post on which you are commenting. No spam, personal attacks, or general nastiness. I will be watching and will delete comments I find irrelevant, offensive and unnecessary.