wuwuxin 28 Posted September 6, 2021 I want a class to be pure static, which doesn't allow instantiating (except through a static method for creating singleton). Is that doable in Delphi? Share this post Link to post
David Schwartz 426 Posted September 6, 2021 (edited) If it's for a singleton, treat it like a Factory method with the constructor hidden. The static method would create it initially if it's NIL, and otherwise return the existing reference. Also, make the constructor Create a strict private member of the class and only reference it through the static factory method in the same unit. Edited September 6, 2021 by David Schwartz Share this post Link to post
Dalija Prasnikar 1396 Posted September 6, 2021 4 hours ago, David Schwartz said: If it's for a singleton, treat it like a Factory method with the constructor hidden. The static method would create it initially if it's NIL, and otherwise return the existing reference. Also, make the constructor Create a strict private member of the class and only reference it through the static factory method in the same unit. You cannot make such singleton in Delphi. Public TObject constructor will be always visible and you cannot hide it, The only way to disable access to the constructor is to define singleton API as interface and have public factory method that returns interface, and then put class implementation inside implementation section of the unit making it inaccessible to the outside world. Share this post Link to post
Lars Fosdal 1792 Posted September 6, 2021 I wish the "class abstract" declaration would have prevented .Create instantiation. 1 Share this post Link to post
Guest Posted September 6, 2021 4 hours ago, wuwuxin said: I want a class to be pure static, which doesn't allow instantiating (except through a static method for creating singleton). Is that doable in Delphi? If i do understand right and that you need a class that is no on the heap, then the answer is no, Delphi doesn't have static classes, though it is easy for the compiler to be made to do so. On other hand the closest thing to static classes (on the stack or global as preallocated) is to use records, managed records is there to close some of this gap, but still these are records not classes. I wish as a feature to have this declaration for classes var C : TMyClass; static; // C here is global and will not reside on heap D : TMyClass; static; auto; // D is global and its default constructor will be handled as class constructor, same for its destructor, D is not on the stack procedure Test; var E : TMyClass; static; // E reside on the stack F : TMyClass; static; auto; // same as D but on the stack G : TMyclass; auto; // G is on the heap but managed just like strings, means the compiler will manage its constructor and destructor begin E := TMyclass.Create; // manually managed hence need creating and free manually; F.DoSomething; // the compiler will make sure to call the default Creat and Free in Test, F is on the stack ! G.DoSomething; // same as F but G reside on the heap Share this post Link to post
David Schwartz 426 Posted September 6, 2021 19 minutes ago, Dalija Prasnikar said: You cannot make such singleton in Delphi. Public TObject constructor will be always visible and you cannot hide it, The only way to disable access to the constructor is to define singleton API as interface and have public factory method that returns interface, and then put class implementation inside implementation section of the unit making it inaccessible to the outside world. I offered up a solution. It may not be ideal, but as you say, that's impossible. So, yeah, we've gotta make do with what we've got. The language purists have managed to keep stuff like this from being properly implemented forever. There are all kinds of holes and back-doors and things that can only be done with awkward work-arounds in Delphi, and I don't expect that will ever change. Everywhere I've worked has all sorts of unwritten rules about what devs can and cannot do in order to deal with this stuff, and when I dig into the code there are also lots of violations of said rules, mostly by those who made the rules up in the first place. ("Do as I say, not as I do!") 1 Share this post Link to post
Fr0sT.Brutal 900 Posted September 6, 2021 Is it really so important to disallow instance creation? 1 Share this post Link to post
Dalija Prasnikar 1396 Posted September 6, 2021 There is another way to prevent instance creation - or at least misuse - having public constructor that raises exception. TSingleton = class private class var FInstance: TSingleton; constructor CreateSingleton; class destructor ClassDestroy; public constructor Create; class function Instance: TSingleton; static; end; class destructor TSingleton.ClassDestroy; begin FInstance.Free; end; constructor TSingleton.Create; begin raise Exception.Create('Singleton instance cannot be directly constructed'); end; constructor TSingleton.CreateSingleton; begin // actual constructor end; class function TSingleton.Instance: TSingleton; begin if not Assigned(FInstance) then FInstance := TSingleton.CreateSingleton; Result := FInstance; end; 7 Share this post Link to post
Der schöne Günther 316 Posted September 6, 2021 Suggestion: Throw the ENoConstructException from System.SysUtils, not a regular Exception 😉 4 Share this post Link to post
Stefan Glienke 2002 Posted September 6, 2021 If you don't want instances, then don't make it a class - this ain't Java. 1 3 2 Share this post Link to post
DPStano 15 Posted September 7, 2021 can ctor be private? strict private constructor Create; end; Share this post Link to post
Dalija Prasnikar 1396 Posted September 7, 2021 12 minutes ago, DPStano said: can ctor be private? strict private constructor Create; end; Yes, it can. But the problem is not in hiding your constructor. Every class in Delphi descends from base TObject class, whether you explicitly state that in class declaration or not TSingleton = class TSingleton = class(TObject) And TObject has public constructor Create. That means its every descendant and consequently every other class in Delphi has public constructor Create. Since it is public it is accessible and you cannot prevent people using it. So, even if you hide constructor in descendant class, someone can write TSingleton.Create and this will not call your hidden constructor, but TObject default constructor. The only way to hide that TObject constructor is to add public constructor with same name in your class, like in example I posted. But then you again have problem with having publicly accessible constructor and people can instantiate more than single object instance. If that public constructor raises exception, then at least code will fail at runtime showing that this constructor shouldn't be used. Share this post Link to post
Joseph MItzen 251 Posted September 8, 2021 On 9/6/2021 at 7:05 AM, Stefan Glienke said: If you don't want instances, then don't make it a class - this ain't Java. Thank you! Delphi has a method for grouping a collection of common procedures/functions together... it's called a Unit. 2 Share this post Link to post