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

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.

Related

Does reference counting still works with Delphi Interfaces when you don't provide a guid?

I have the following interface:
type IDataAccessObject<Pk; T:class> = interface
getByPrimaryKey(key: PK) : T;
//... more methods
end;
And an implementation of the interface as follows:
type TMyClassDAO = class(TInterfacedObject, IDataAccessObject<integer, TMyClass>)
getByPrimaryKey(key:integer) : TMyClass;
// more methods
end;
Note that I am not providing a guid for the interface (because every instantiation of the previous generic interface is a different interface and they should not share the same guid). However I am not sure whether that does not break reference counting implemented by TInterfacedObject?
Reference counting does not rely on a GUID, but on _AddRef() and _Release() method implementations.
Since you inherit from TInterfacedObject, reference counting will work for all of your object instances.
The only thing you lose if you don't provide a GUID is the ability to query one interface from another, such as in calls to the Supports() function, QueryInterface() interface method, and the is and as operators.

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

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.

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.

How do I mock a class that doesn't have virtual methods?

Let's assume you have a very well designed Delphi project, which respects the dependency injection and some other good practices.
Now let's assume you need to mock a class defined as:
TMyClass = class
public
procedure Method1;
procedure Method2
end;
Method1 and Method2 are not virtual. What do you do in this case? To mock an object we need to inherit it and override every method you want to mock, but it is not possible in this case because they are not virtual. Should I change the source code to add virtual on every method I need to mock? Is not it bad?
Edit
I was thinking about creating a compiler directive to make all fields in the class to be virtual, is it a good ideia? Only my test suite is going to set the compiler directive.
EDIT2*
Embarcadero should provide an easy way of changing a method pointer of a class to another method point, without the need for virtual.
Make the methods virtual so you can mock them. (They don't need to be abstract.)
If you cannot do that, then wrap the class with another class. Make the wrapper's methods virtual, and in the default implementation, just forward call calls to the original class. Wherever your program uses the original class, replace it with the wrapper. Now, mock the wrapper.
To mock an object we need to inherit
it, but it is not possible in this
case.
I'd recommend that every class that you say "I need to mock this" should end up being based on an interface.
In other words, if you have methods that need to be mocked, they should be put into an interface, and then the class to be mocked implements that interface. Then, you create the mock by implementing the same interface in the mock object.
The alternative is to use a Mocking library. You can look at these SO question:
What is your favorite Delphi mocking library?
and this framework includes mocking objects as well:
http://code.google.com/p/emballo/
Mocking objects should also encourage the proper use of dependency injection in your code.
You should not only make the methods virtual, you should declare a pure virtual base class, and make the other classes use only the pure virtual base class name. Now you can use what we call the "Liskov substitution principle", and you can make as many concrete subtypes of the abstract base class as you need. Since the abstract base class works just like an Interface works in delphi, minus the reference counting part, you get the best of both worlds. You can really keep your app code simple, and reduce bad coupling this way, plus you get unit testable "composite objects" that you put together yourself.
// in UnitBase.pas
TMyClassBase = class
public
procedure Method1; virtual; abstract;
procedure Method2; virtual; abstract;
end;
// in UnitReal.pas
TMyClassReal = class(TMyClassbase)
public
procedure Method1; override;
procedure Method2; override;
end;
// in UnitMock.pas
TMyClassMock = class(TMyClassbase)
public
procedure Method1; override;
procedure Method2; override;
end;
In the place that uses "TMyClass", change it to use TMyClassbase:
TMyOtherClass = class(TMyOtherClassBase)
private
FMyThing:TMyClassbase;
public
property MyThing:TMyClassBase read FMyThing write FMyThing;
end;
By connecting TMyOtherclass at runtime you can decide whether to use the real or mock class:
// in my realapp.pas
MyOtherClassObj := TMyotherClass.Create;
MyOtherClassObj.MyThing := TMyOtherClassReal.Create; // real object
// in my unittest.pas
MyOtherClassObj := TMyotherClass.Create;
MyOtherClassObj.MyThing := TMyOtherClassMock.Create; // mock object
(Don't forget to make a way to free MyOtherClassObj.MyThing later, or you'll have a leak)

Resources