Can I make the compiler fail if Create is called explicitly? - delphi

I have many singletons where I don't want the developers to call the constructor Create. Instead they should use the function Instance
TdgpBankBranch = class(TDataGroup)
strict private
class var InstanceVar : TdgpBankBranch;
private
{ Only for internal use }
constructor Create (AOwner : TComponent); reintroduce;
protected
public
class function Instance : TdgpBankBranch;
class function Is_A_Live_Singleton: boolean;
property Rec[Bank, Branch : integer]: TBankBranch read GetRec; default;
end;
I have been shifting the constructors to private. This makes the code analysers complain "Non-public constructor".
I could shift them back to public. Is there a way to make the compiler fail if an attempt is made at using the constructor ?

Moving the constructor to private will prevent other units from being able to call Create() directly, however code inside the same unit as the class will still be able to call it unhindered, due to implicit friendship within a unit. If you don't want any code outside of the class calling Create() directly, even in the same unit, then declare it as strict private so only the class itself can call it directly.

You ask how to stop the compiler from creating an object when somebody calls .create, but what you're trying to do is create a singleton, so it helps to see how others solved this.
In Delphi, singletons are often implemented via a function that's declared in the interface section and which returns an object that's declared in the implementation section of a unit. The function creates the instance if it doesn't exist yet, to provide lazy loading. Cleanup is done via the finalization section.
In your situation, instead of having an instance() function, you just create a global function that gives you an instance.
This approach probably stems from the days before classes and private sections existed, but it's pretty straightforward, and prevents the issue that you're running in to. Look at how TClipboard is implemented. This implementation is not possible in Java or C# because they don't have global functions, or the type of scoping that makes this Delphi implementation work...
Or take a look at this answer by David Heffernan:
Delphi Singleton Pattern
It's even better than TClipboard, because it hides the entire class in the implementation section, truly preventing people to create instances themselves, but you'll have to create an interface for your class.

Related

When implementing an interface in Delphi, does it matter if the implementation methods are not in the public section?

Given the interface below:
ITest = interface ['guidhere']
procedure TestMethod;
end;
Is there any reason to have TestMethod() declared as public in the implementation class? I have put it in both the private and protected sections and it does not seem to make a difference. I am just wondering if there are any guidelines, from a design perspective (or any perspective really), that make the public section the correct section to implement the method in.
does it matter if the implementing methods are not in the public section?
As far as the compiler is concerned. It makes no difference.
That being said. Private methods will still be private, even if you can access them through the interface.
unit unit1;
....
IItest = interface
['{A3D5FEB6-8E29-4EA8-8DC9-7988294EFA65}']
procedure Test;
end;
TTest = class(TInterfacedObject, IItest)
private
procedure Test;
end;
unit unit2;
....
var
TestT: TTest;
TestI: ITest;
begin
TestT:= TTest.Create;
TestI:= TTest.Create;
TestT.Test; //will not compile.
TestI.Test; //works.
The reason for this is that the interface simply has a list of pointers to methods in its VMT. The definition of the method is given in the interface definition.
The compiler only checks if the signatures match.
It does not check the visibility of the method.
As per Allen's comment this is a deliberate design:
Making the methods private or protected will ensure that you can only access them through the interface. This is a way to enforce a usage contract for the intended use of the object.
Note that this is not an error, or even a bad thing.
Properties can give 'access' to private methods as well:
property Items[index: integer] read GetItem write SetItem;
Here GetItem and SetItem are often private.
This forces you to access the Items using the property.
When using properties the implementing methods are protected (or worse :-) as a rule. The same logic applies to both properties and interfaces.
More so for interfaces, because if you mix interface access and regular access you'll run into reference counting issues.
Clean code
Note that you can have as many visibility sections in a class header as you like.
This way you can put all the interfaced methods in one part and all the non-interfaced methods in another.
TTest = class(TInterfacedObject, I1, I2)
//I1 methods
private
... private I1 methods here...
protected
.. more I1 methods
//I2 methods
private
.. some I2 methods
protected
..more I2 methods
//TTest methods
private
//data members
public
constructor Create;
destructor Destroy; override;
end;
That way it's as clear as can be what's what.
I appreciate this is an old question, but the answer is no longer accurate.
I am using Rio, and from the documentation:
All members of an interface are public. Visibility specifiers and storage specifiers are not allowed. (But an array property can be declared as default.)
which is indeed what I observe. An interface defitnion will not allow protected, private or public to be specified.
Edit: To incorporate comments to this answer
At the time of writing the compiler does not enforce any level of visibility on the methods which implement the interface. The methods will be callable through either the interface (interface reference) or through the class (object instance).
As the interface definition insists that all methods are public, when called through an interface reference the implementing methods are public regardless of how they are defined in the implementing class. As a reference to the interface can be obtained from the object then they are callable from the object, although the caller may have to obtain the interface reference first.
Given that the implementing methods are callable as public through the interface you should consider how helpful it is to not make them public in your class. Restricting the visibility of the methods in the class when they are public in the interface seems to me to be making the code less clear, but other opinions are available!
One of the comments mentioned delegation of the interface. This seems to me to be a distraction as it simply means that when the object retruns the interface reference it returns the reference from the delgated object (which could itself delegate the interface) and ultimately it is the methods of that object whaich are called.
So any class which implements an interface makes the methods which implement the interface available as public when called through the interface.

override, virtual/dynamic in Delphi constructors

The one with virtual/dynamic
// declare in Child Class
constructor Create; virtual;
constructor TChildClass.Create;
begin
inherited;
end;
The one with override.
// declare in Child Class
constructor Create; override;
constructor TChildClass.Create;
begin
inherited;
end;
The one with nothing
// declare in Child Class
constructor Create;
constructor TChildClass.Create;
begin
inherited;
end;
Are these the same thing? It looks confusing.
Yes, there is a difference, but let's deal with the virtual keyword in more basic OOP terms first, yet still how it applies to Delphi methods.
When you declare a derived (child) class, and implement a method as "override", it means that you're overriding (surprise) the matching method of the base class.
This means that you can write code like this:
var child : TBaseClass;
begin
child := TChildClass.Create; // note that it is stored in TBaseClass variable
child.VirtualMethodDefinedInBaseClassThatHasBeenOverriddenInChildClass;
This will call the method in the child class, even if the variable is defined to be of the base class type. This is the whole purpose of virtual methods, you can access the object through a reference of a more general type, and still call methods that have been written for the particular type of object you're dealing with.
If you have a virtual method in the base class that you chose not to override in the child class, but instead reintroduce, you're effectively replacing it in some cases. Note that in most cases you need to tell the compiler that you really meant to do this, though I'm unsure about what Delphi requires here.
Basically, if your variable is of type TBaseClass, and you call a virtual method on it, that has been reintroduced in the TChildClass, it will still call the method in the base class.
However, if your variable is of type TChildClass, and you call that method on it, you will get the new method instead.
Now, for constructors, in Delphi, it is slightly different.
The point of virtual constructors is to be able to virtually construct objects, and to do that, Delphi also has "class types".
You can say this:
type TClassToUse = class of TBaseClass;
var cls : TClassToUse;
obj : TBaseClass;
begin
cls := TChildClass;
obj := cls.Create;
(note that my Delphi knowledge is a bit rusty here, if anyone spots bugs or glaring problems in the above code, please let me know or just fix it)
Here we store a "class" in a variable, and then ask the class to please construct an object for us. This allows us to switch out which class to create, but we also need to declare the constructors we want to use virtual, otherwise we will have problems.
So in the above code, if you declared the constructor as virtual in TBaseClass, and then override it in TChildClass (which the code is actually using in cls), the overridden constructor is the one that will be used.
If, on the other hand, you don't declare the constructor as virtual, we're back to the base class constructor. Virtual basically means to figure out the right method to execute at runtime, whereas non-virtual will figure it out at compile time.
Reintroduction as described for normal methods above, also works this way.
However, virtual constructors are only used as virtual when used through a class type.
No, static and virtual methods are not the same thing.
And override is a case of virtual method.
http://en.wikipedia.org/wiki/Virtual_function
http://docwiki.embarcadero.com/RADStudio/XE4/en/Methods#Method_Binding
Constructors bring nothing special here - they conform to the same rules as other methods for the question

Assigning interface pointers in a Delphi 6 class declaration?

Despite years of Delphi programming I just ran into a class declaration style I had never seen for a class that supports IUnknown:
TBCUnknown = class(TBCBaseObject, IUnKnown)
private
FRefCount: integer;
FOwner : Pointer;
protected
function IUnknown.QueryInterface = NonDelegatingQueryInterface;
function IUnknown._AddRef = NonDelegatingAddRef;
function IUnknown._Release = NonDelegatingRelease;
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
...
As you can see, assignments of class methods to IUnknown interface methods are being done right in the class declaration. This looks really strange to me especially since I don't see how the IUnknown methods could be assigned to, before the constructor is called. Is this some kind of compile-time shortcut for making assignments between a class's methods and the interface pointers for an interface the class accepts, that are later resolved at run-time? If someone could provide a little information on how this works and what Delphi idiom supports this kind of construct I'd like to know.
It's called Method Resolution Clause and it allows you to specify which method actually implements the specified interface method. This means that the implementing method can have a different name than the method declared in the interface (but the method signature still has to match). Without the clause, Delphi automatically resolves the implementation methods based on their names.
In your example, the declaration means that IUnknown._AddRef is implemented by TBCUnknown.NonDelegatingAddRef and IUnknown._Release by TBCUnknown.NonDelegatingRelease.
As far as I know, this has been supported from the beginning when interface support was added to the language. You probably haven't noticed it because it's not used or needed so often.
This is what is known as a Method Resolution Clause. To quote from the documentation:
You can override the default name-based mappings by including method resolution clauses in a class declaration. When a class implements two or more interfaces that have identically named methods, use method resolution clauses to resolve the naming conflicts.

Class constructor not called when class registration is done in that class constructor

I am writing a simple dependency injection / inversion of control system based on a TDictionary holding abstract class references with their respective implementor classes.
My goals are:
Avoid direct instantiation by type (obviously).
Inclusion of a class' unit in the dpr should be enough to have it registered and be available for selection and instantiation through the di/ioc system.
Declare concrete implementing classes in implementation section only.
Use class constructors instead of initialization sections.
Btw, I am aware that using class constructors to take advantage of smart linking and wanting the inclusion of a unit to be enough to make a class available are defeating each other. I want to use class constructors instead of initialization sections for other reasons as well. And I would like to keep all class initialization/registration code together instead of having to split it between the class constructor and initialization section.
Problem
I want the registration of the class into the factory to be in the class constructor. Unfortunately, the compiler doesn't think the class is "touched" by just using its type in its own class constructor.
When I put the registration function in the initialization section, then the compiler does think the class is touched and calls the class constructor. But that defeats the object of my exercise of keeping all class initialization code in the class constructor.
Two questions
Should the compiler consider the use of the class in its own class constructor "touching the class" or is that too much to expect the compiler to do?
Does anybody have any clever ideas on how I can still achieve my goals without using the initialization section?
Example
The abstract classes used in the application:
TSite = class abstract (TObject)
function GetURL: string; virtual; abstract;
property URL: string read GetURL;
end;
TSites = class (TList<TSite>);
TThisApplication = class abstract (TObject)
function Sites: TSites; virtual; abstract;
end;
The concrete implementing class (declared in the implementation section!) for TThisApplication
TThisApplicationConcrete = class(TThisApplication)
class constructor ClassCreate;
strict private
FSites: TSites;
function Sites: TSites; override;
end;
class constructor TThisApplicationConcrete.ClassCreate;
begin
RegisterImplementorClass(TThisApplication, TThisApplicationConcrete);
end;
function TThisApplicationConcrete.Sites: TSites;
var
SiteList: TSites;
begin
if not Assigned(FSites) then begin
SiteList := TSites.Create; // Change to use factory
//RetrieveSites(SiteList);
FSites := SiteList;
end;
Result := FSites;
end;
The function to get an instance of TThisApplication:
function ThisApplication: TThisApplication;
var
ImplementorClass: TClass;
begin
ImplementorClass := GetImplementorClass(TThisApplication);
if Assigned(ImplementorClass) then begin
Result := ImplementorClass.Create as TThisApplication;
end else begin
Result := nil;
end;
end;
This is currently coded in a separate function, but it w/could be moved to the factory.
Full example code
If anybody would like to experiment, I have the full code of my test projects available at : http://www.bjsoftware.com/delphistuff/stackoverdlow/classconstructors.zip
Zip contents:
4 projects all using the same source files, differing only in conditional defines (that's why the dproj's are also included)
4 source files
groupproj and its dsk with all 4 projects
RunTestApps.cmd to run all 4 projects
Results.txt with the output of my run of the RunTestApps.cmd
WriteUp.txt with the text of this question
Please bear in mind that at all times you need to do a "Build All Projecs" because all dcu's and exe's are going to the source dir and otherwise you are going to face a lot of errors and/or confusion because the exe isn't doing what its name indicates.
This is as expected. As Uwe pointed out, a self-referential class constructor isn't enough to trigger inclusion. Placing the reference in the initialization section will do the trick since that is outside the class itself. Trying to self-reference a class for inclusion is akin to trying pull yourself out of a deep hole by pulling on your own suspenders.
As long as you don't use the class anywhere outside the class itself, the compiler takes this as the class not used at all and hence won't call the class constructor. So I guess you have to use the intialization section instead of tweaking the code to fool the compiler. Take the pragmatic approach instead of the dogmatic one. It will be more readable anyway.
I think you expect the class constructor to work differently than it has been designed to. Class constructor don't get called "just before" the first create. (Not in WIN32 delphi at least). If a class is referenced, its class constructor will run before the unit's initialization code.
If the only reference that you have to your class happens to be inside said class, then no code actually linked into your application refer to said class. Therefore, its class constructor will never get called.
I believe register functions belongs to the initialization section. Having the register function there will force the class constructor to also be executed. I don't see why you would want/require the register code to be placed into the class constructor.
If you want more information about the way class constructor/destructor works, you can read this pretty good article by Allen Bauer:
http://blogs.embarcadero.com/abauer/2009/09/04/38899

Can a Delphi generic class descend from its class argument?

I've been trying to define a generic, inheritable TSingleton class. Here's what I had in progress:
TSingleton<RealClass, InheritsFrom : class> = class(InheritsFrom)
strict private
class var FInstance : RealClass;
protected
procedure InstanceInitialization;virtual;
public
destructor Destroy; override;
class procedure Create; reintroduce;
class function Instance : RealClass;
class procedure InstanceFree;
end;
The goal was to be able to "insert" the singleton pattern in an inheritance tree. so instead of declaring something like this :
TMySingletonComponent = class(TComponent)
end;
And need to implement the singleton pattern there, I would declare something like this :
TMyGenericSingletonComponent = class(TSingleton<TMyGenericSingletonComponent,TComponent>)
end;
Sadly, this won't work. I'm getting the following error(In D2010):
TSingleton<RealClass, InheritsFrom : class> = class(InheritsFrom) ///E2021 Class type required
Now I was wondering, would this work in Delphi XE? Is there some "clean hack" I could use to make this work in D2010? Is there some fundamental reasons why this can't work?
By design, you can't create a generic class which derives from one of its type arguments.
No, that won't work. You're trying to define a class in terms of itself. Whatever you put inside the parameters has to be fully defined already.
What do you want to obtain?
IMHO, singletons are evil. They were introduced because of bad OOP design of C++ (for access to input/output streams in console applications, as far as I remember). And they tend to be like hell to maintain.
You can always live without them. It's definitively not a "Delphi classical" way of programing, because Delphi doesn't suffer the C++ problems I mentioned.
Some Java project (ab)uses of singleton. Google for it, and you'll find out what I mean.
Use a property of a common class with a getter, initializing an instance if the corresponding field is still nil, or directly returning the field pointer to the instance if it was already created. You'll have the singleton feature, with good performance, nice code, good OOP practice (no "global" class), and the ability to run the class without any singleton feature, if you don't need this feature later (for testing purpose, for instance).

Resources