Hiding the TObject.Create constructor

By | July 28, 2011

If you design your classes you may get to a point where you want to have multiple overloaded constructors in your class. But all these overloaded constructors have parameters and a parameter-less constructor doesn’t make sense. And it should be forbidden to call it. Unfortunately Delphi doesn’t allow you to hide the inherited TObject.Create constructor and you end up with a class where you implement the parameter-less constructor just to throw an exception.

But why should you implement something that you obviously do not want anybody to call. Well, you do not need to. You can hide the inherited TObject.Create constructor. All you need is a small “helper” class between your base class and your derived class that does nothing more than moving the inherited constructor to be strict private. Why strict private and not private? Because strict private also prohibits calling it from the unit you’ve declare the “helper” class.

TNoParameterlessContructorObject = class(TObject)
strict private
  constructor Create;
end;

6 thoughts on “Hiding the TObject.Create constructor

  1. Christoph

    Wait…THAT is the answer?

    How many times have I cursed Delphi because of this?!

    Thanks for the hint!

  2. Rudy Velthuis

    I don’t quite get it. AFAICT, it is very well possible to hide TObject.Create. Simply declare one or more other Create constructors and you should not be able to call the parameterless Create anymore. There is no need to redeclare it as strict private.

    1. karl pritchett

      If you overload the Create constructor, then TObjects Create is available
      type
      TSomething=class
      constructor Create(a:Integer); overload;
      constructor Create(a,b:Integer); overload;
      end;

      var MySomething:TSomething;
      MySomething := TSomething.Create; // oops, should not use this Create

      Changing the inherited class to one with a strict private Create stops this

  3. Rudy Velthuis

    FWIW, I tried it and it doesn’t work, for me. This compiles fine:

    unit Unit15;
     
    interface
     
    type
      TPreDerived = class
      strict private
        constructor Create;
      end;
     
      TDerived = class
      public
        constructor Create(A: Integer); overload;
        constructor Create(B: string); overload;
      end;
     
    implementation
     
    // snipped
     
    initialization
      if (TDerived.Create = nil) then ;
     
    end.

    Main prog:

    program Project30;
     
    {$APPTYPE CONSOLE}
     
    uses
      SysUtils,
      Unit15 in 'Unit15.pas';
     
    var
      D: TDerived;
     
    begin
      D := TDerived.Create;
    end.

Comments are closed.