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

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.

Related

Multiple generation of Obj with a generic class

I'm having some trouble with generics and constructors.
I would like to have a Generic class that can handle (and create) multiple objects of the same class. Moreover, I have some code that I would like to use whatever the specific class actually is.
I thought Generics are a good solution to this, but I'm not quite sure.
type
TMultiBlock<T: IBlock, constructor> = class(TObject)
blocks: array of array of T;
constructor Create(const owner: someClass, const n: integer);
end;
constructor TMultiBlock<T>.Create(const owner: someClass, const n: integer);
var
i: integer;
begin
for i := 0 to n-1 do
T.Create();
end;
The solution above works, but the Create() that is called is not the one of the class T that I give to the Generic.
I know that I can do the Create outside the TMultiBlock class, since I know class T there, as show below:
TM := TMultiBlock<TFinestra>.Create();
for i := 0 to n do
begin
TM.blocks[i] := TFinestra.Create();
end;
Here the class TFinestre is one of the class that I want to use in the Generic. But the thing is that I want to do some common operations on the T element, and these operation will be common to whatever the T type is, so I would like to do them on the TMultiBlock.
IBlock is an interface implemented by each class of type T.
An Interface is, in OOP terms, a pure abstract definition. It can be implemented by lots of different classes. You can't create objects from an interface (unless the interface gives you a method to create an object), you can get an interface from an Object if that object supports it. As all interfaces are implemented by a class then they can do different things, but ultimately what they do is dependent on what the object is, so you are back to having to know the class.
If you want to create the objects you have to know the class of the object you are creating. The interface could provide a method for returning the class of the object which is implementing the interface, allowing you to create more of them, but then you may as well use that class.
If your different types do not have a common ancestor, then you can specify, as you have, that T must support an interface, but you still instantiate the TMutliBLOCK<T> with a class. As interfaces are always implemented by a class then T will always derive from TObject so it will always support Create. The problem is you can't call T.Create unless IBlock includes the definition of Create ...
This means that you can have a TMulitBLOCK and a TMultiBLOCK but each would be holding the objects you have declared for it. If they're not inheriting from a common class then you would not be able to restrict the type of T to that common ancestor.
You can check that the type you are using supports an interface in the constructor, and then restrict to TObject.
TMultiBLOCK<T: class> = class(TObject)
protected
blocks: TArray<T>;
public
constructor Create(AOwner: pSomeObject; nSize: Integer);
end;
constructor TMultiBLOCK<T>.Create(AOwner: pSomeObject; nSize: Integer);
begin
if(not Supports(T, IBlock)) then
raise EInvalidCast.Create('Class '+T.ClassName+' must support IBlock')
else
...
end;
To call the members of IBlock you will need to get an interface pointer for each object. Bear in mind that depending on the implementation in the different implementing classes then when the interface references go out of scope the object may delete itself. To prevent that happening you probably want to store the interface references alongside the objects when you create them so the reference count is held above 0.
If you can organise the code so that all members are derived from a common ancestor then you can restrict your TMultiBLOCK<T> to that common ancestor, rather than a common interface.

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.

Problems with memory leaks using interface?

I have a method that returns a IInterface, the method contain a dictionary created like this:
Dictionary:= TDictionary<string, IInterface>.Create;
That contains:
Dictionary.Add('key', TPerson.Create(DatabaseCon)as IInterface);
When I quit my ongoing program I get an error message memory leaks on the object Tperson.
I've tried in the class destructor method the following:
private //Global variabels
Person:TPerson;
I: IInterface;
begin // in the destructor method of the class
Person:= IInterface as TPerson;
Person.Free;
end;
But I still get the error... How do I release the TPerson.Create(DatabaseCon) as IInterface)?
Or would it be better to save the TPerson as a string in an INI file and then drag the string name out and turn it into an object .. But how??
The structure of the program:
Inf1= Interface(IInterface)
//some functions
Inf2=Interface(Inf1)
//Some functions
TPerson= class(TInterfacedPersistent,Inf2)
// All my functions.
I can get it to work if I:
Dictionary.Add ('key', Person) as IInterface);
Where I in the Create method of the class write:
Person:= TPerson.Create(DatabaseCon);
and in the destructor method writes:
Person.Free;
but is it not wrong to do so? since the class person must first be instantiated when I access the dictionary?
The most likely explanation is that TPerson does not use interface reference counting to manage lifetime. To be sure we'd need to know exactly how TPerson implements IInterface. Unfortunately that key detail was omitted from the question.
If TPerson derives from TInterfacedObject, and so has lifetime managed by reference counting, then your code will not leak. So, I'm reasonably confident that the problem is that your class's implementation of IInterface does not free the object when its reference count goes to zero.
Assuming I am correct, then you have a couple of options to resolve the issue:
Change your class to implement interface reference counted lifetime management.
Use TObjectDictionary<TKey,TValue> rather than TDictionary<TKey,TValue>. Arrange that the value type TValue is TPerson rather than IInterface. And arrange that the dictionary owns its values so that it can free them when they are removed.
Update: Your update shows that my hunch was correct. Your class does not manage lifetime with interface reference counting.

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

In Delphi, how can you check if an IInterface reference implements a derived but not explicitly-supported interface?

If I have the following interfaces and a class that implements them -
IBase = Interface ['{82F1F81A-A408-448B-A194-DCED9A7E4FF7}']
End;
IDerived = Interface(IBase) ['{A0313EBE-C50D-4857-B324-8C0670C8252A}']
End;
TImplementation = Class(TInterfacedObject, IDerived)
End;
The following code prints 'Bad!' -
Procedure Test;
Var
A : IDerived;
Begin
A := TImplementation.Create As IDerived;
If Supports (A, IBase) Then
WriteLn ('Good!')
Else
WriteLn ('Bad!');
End;
This is a little annoying but understandable. Supports can't cast to IBase because IBase is not in the list of GUIDs that TImplementation supports. It can be fixed by changing the declaration to -
TImplementation = Class(TInterfacedObject, IDerived, IBase)
Yet even without doing that I already know that A implements IBase because A is an IDerived and an IDerived is an IBase. So if I leave out the check I can cast A and everything will be fine -
Procedure Test;
Var
A : IDerived;
B : IBase;
Begin
A := TImplementation.Create As IDerived;
B := IBase(A);
//Can now successfully call any of B's methods
End;
But we come across a problem when we start putting IBases into a generic container - TInterfaceList for example. It can only hold IInterfaces so we have to do some casting.
Procedure Test2;
Var
A : IDerived;
B : IBase;
List : TInterfaceList;
Begin
A := TImplementation.Create As IDerived;
B := IBase(A);
List := TInterfaceList.Create;
List.Add(IInterface(B));
Assert (Supports (List[0], IBase)); //This assertion fails
IBase(List[0]).DoWhatever; //Assuming I declared DoWhatever in IBase, this works fine, but it is not type-safe
List.Free;
End;
I would very much like to have some sort of assertion to catch any mismatched types - this sort of thing can be done with objects using the Is operator, but that doesn't work for interfaces. For various reasons, I don't want to explicitly add IBase to the list of supported interfaces. Is there any way I can write TImplementation and the assertion in such a way that it will evaluate to true iff hard-casting IBase(List[0]) is a safe thing to do?
Edit:
As it came up in the one of the answers, I'm adding the two major reasons I do not want to add IBase to the list of interfaces that TImplementation implements.
Firstly, it doesn't actually solve the problem. If, in Test2, the expression:
Supports (List[0], IBase)
returns true, this does not mean it is safe to perform a hard-cast. QueryInterface may return a different pointer to satisfy the requested interface. For example, if TImplementation explicitly implements both IBase and IDerived (and IInterface), then the assertion will pass successfully:
Assert (Supports (List[0], IBase)); //Passes, List[0] does implement IBase
But imagine that somebody mistakenly adds an item to the list as an IInterface
List.Add(Item As IInterface);
The assertion still passes - the item still implements IBase, but the reference added to the list is an IInterface only - hard-casting it to an IBase would not produce anything sensible, so the assertion isn't sufficient in checking whether the following hard-cast is safe. The only way that's guaranteed to work would be to use an as-cast or supports:
(List[0] As IBase).DoWhatever;
But this is a frustrating performance cost, as it is intended to be the responsibility of the code adding items to the list to ensure they are of the type IBase - we should be able to assume this (hence the assertion to catch if this assumption is false). The assertion isn't even necessary, except to catch later mistakes if anyone changes some of the types. The original code this problem comes from is also fairly performance critical, so a performance cost that achieves little (it still only catches mismatched types at run-time, but without the possibility to compile a faster release build) is something I'd rather avoid.
The second reason is I want to be able to compare references for equality, but this can't be done if the same implementation object is held by different references with different VMT offsets.
Edit 2: Expanded the above edit with an example.
Edit 3: Note: The question is how can I formulate the assertion so that the hard-cast is safe iff the assertion passes, not how to avoid the hard-cast. There are ways to do the hard-cast step differently, or to avoid it completely, but if there is a runtime performance cost, I can't use them. I want all the cost of checking within the assertion so that it can be compiled out later.
Having said that, if someone can avoid the problem altogether with no performance cost and no type-checking danger that would be great!
One thing you can do is stop type-casting interfaces. You don't need to do it to go from IDerived to IBase, and you don't need it to go from IBase to IUnknown, either. Any reference to an IDerived is an IBase already, so you can call IBase methods even without type-casting. If you do less type-casting, you let the compiler do more work for you and catch things that aren't sound.
Your stated goal is to be able to check that the thing you're getting out of your list really is an IBase reference. Adding IBase as an implemented interface would allow you to achieve that goal easily. In that light, your "two major reasons" for not doing that don't hold any water.
"I want to be able to compare references for equality": No problem. COM requires that if you call QueryInterface twice with the same GUID on the same object, you get the same interface pointer both times. If you have two arbitrary interface references, and you as-cast them both to IBase, then the results will have the same pointer value if and only if they are backed by the same object.
Since you seem to want your list to only contain IBase values, and you don't have Delphi 2009 where a generic TInterfaceList<IBase> would be helpful, you can discipline yourself to always explicitly add IBase values to the list, never values of any descendant type. Whenever you add an item to the list, use code like this:
List.Add(Item as IBase);
That way, any duplicates in the list are easy to detect, and your "hard casts" are assured to work.
"It doesn't actually solve the problem": But it does, given the rule above.
Assert(Supports(List[i], IBase));
When the object explicitly implements all its interfaces, you can check for things like that. And if you've added items to the list like I described above, it's safe to disable the assertion. Enabling the assertion lets you detect when someone has changed code elsewhere in your program to add an item to the list incorrectly. Running your unit tests frequently will let you detect the problem very soon after it's introduced, too.
With the above points in mind, you can check that anything that was added to the list was added correctly with this code:
var
AssertionItem: IBase;
Assert(Supports(List[i], IBase, AssertionItem)
and (AssertionItem = List[i]));
// I don't recall whether the compiler accepts comparing an IBase
// value (AssertionItem) to an IUnknown value (List[i]). If the
// compiler complains, then simply change the declaration to
// IUnknown instead; the Supports function won't notice.
If the assertion fails, then either you added something to the list that doesn't support IBase at all, or the specific interface reference you added for some object cannot serve as the IBase reference. If the assertion passes, then you know that List[i] will give you a valid IBase value.
Note that the value added to the list doesn't need to be an IBase value explicitly. Given your type declarations above, this is safe:
var
A: IDerived;
begin
A := TImplementation.Create;
List.Add(A);
end;
That's safe because the interfaces implemented by TImplementation form an inheritance tree that degenerates to a simple list. There are no branches where two interfaces don't inherit from each other but have a common ancestor. If there were two decendants of IBase, and TImplementation implemented them both, the above code wouldn't be valid because the IBase reference held in A wouldn't necessarily be the "canonical" IBase reference for that object. The assertion would detect that problem, and you'd need to add it with List.Add(A as IBase) instead.
When you disable assertions, the cost of getting the types right is paid only while adding to the list, not while reading from the list. I named the variable AssertionItem to discourage you from using that variable elsewhere in the procedure; it's there only to support the assertion, and it won't have a valid value once assertions are disabled.
You are right in your examination and as far as I can tell there is really no direct solution to the problem you've encountered. The reasons lies in the nature of inheritance among interfaces, which has only a vague resemblance of inheritance among classes.
An inherited interfaces is a brand new interface, that has some methods in common with the interface it inherits from, but no direct connection. So by choosing not to implement the base class interface, you are making a specific assumption that the compiled program will follow: TImplementation does not implement IBase.
I think "interface inheritance" is somewhat of a misnomer, interface extension makes more sense! A common practice is to have a base class implementing the base interface, and than derived classes implementing the extended interfaces, but in case you want a separate class that implements both simply list those interfaces. It there a specific reason you want to avoid using:
TImplementation = Class(TInterfacedObject, IDerived, IBase)
or just you don't like it?
Further Comment
You should never, even hard type cast an interface. When you do "as" on an interface it will adjust the object vtable pointers in the right way... if you do a hard cast (and have methods to call) you code can easily crash. My impression is that you are treating interfaces like objects (using inheritance and casts in the same way) while their internal working is really different!
In Test2;
You shound't retype IDerived as IBase by IBase(A) but with:
Supports(A, IBase, B);
And adding to list can be just:
List.Add(B);

Resources