Hey guys
Hey guys,
How do I create a class which has only a private constructor? I have tried but doesn't work as expected. I am able to hide the constructor from Delphi IDE's auto-completion but the users are still able to call a parameterless constructor :( I want to implement the Builder pattern in Delphi and to achieve that I need to hide the class constructors thus the class can only be instantiated through the builder object. I want something close to done here https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit/Retrofit.java#L230-L244 :D
Thanks in advance :D
How do I create a class which has only a private constructor? I have tried but doesn't work as expected. I am able to hide the constructor from Delphi IDE's auto-completion but the users are still able to call a parameterless constructor :( I want to implement the Builder pattern in Delphi and to achieve that I need to hide the class constructors thus the class can only be instantiated through the builder object. I want something close to done here https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit/Retrofit.java#L230-L244 :D
Thanks in advance :D
I'm not an expert about pattern, but what your talking about looks like more an Interface than an object.
ReplyDeletePaul TOTH Thanks :D I want something close to done here https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit/Retrofit.java#L230-L244 :D
ReplyDeleteit's not possible to hide the inherited public constructor of an objet, you can only override it but it still public. That's why I've think about Interface that can not be instanciated :)
ReplyDeletePaul TOTH :( Sorry sorry, that you wrote is right, I will think better about that :D Many thanks.
ReplyDeleteThis article handles the problem quite well: http://www.yanniel.info/2011/08/hide-tobject-create-constructor-delphi.html
ReplyDeleteTMyObject = class
ReplyDeletepublic
procedure Create;
private
constructor CreatePrim(aSomeParams : TSomeParams) : TMyObject;
constructor TMyObject.CreatePrim(aSomeParams : TSomeParams) : TMyObject;
begin
inherited Create;
f_Data := aSomeParams;
end;
procedure Create;
begin
Assert(false);
end;
It's dangerous. If a constructor is hidden, you will often end up calling the ancestor class's constructor - without a warning from the compiler. Uwe Raabe's link contains a workaround for this, to hide the inherited constructor(s) with methods with the same name.
ReplyDeleteI was sure there was a QP report to add a compiler warning in this situation, to help prevent partially initialised objects, but I couldn't find one. So I made one: https://quality.embarcadero.com/browse/RSP-11613
By the way, another way to approach this is to provide the interface, and have the implementing class entirely hidden - ie defined in a type clause in the implementation part of a unit. To get an instance, external units can then only call the function you provide.
ReplyDeleteIt makes polymorphic OO via inheritance a bit more difficult though.
Uwe Raabe it handles only partially, you can still call it through a metaclass:
ReplyDeletetype
TDummy = class (TObject);
var
meta : TClass;
obj : TObject;
begin
meta := TDummy;
obj := meta.Create;
now obj is a TSomeClass created with the original TObject constructor.
Only fix would be to have the original TObject.Create constructor be virtual, rather than static.
Why not just use a record? No constructor to hide...
ReplyDelete