I am a Java developer who has recently been thrust into wearing a Delphi developer hat.
As is typically the case in such situations, I wind up trying to do things in Delphi while still using my 'Java' mindset, and I get confounded when they don't work.
Today's issue is the notion of an interface. In Java, I can define an interface, give it some methods, and later declare a class that implements that interface.
I have tried to do the same thing in Delphi, and got my fingers burned. I declared an interface that extended IInterface. But when it came time to implement that interface, I was greeted by a number of unimplemented methods errors for methods I didn't declare (QueryInterface, _AddRef, _Release).
A little Google told me that I needed to extend the TInterfacedObject instead of TObject. This made me uneasy because it suggests that I cannot simply add an interface to some third-party class unless that class ultimately extends TInterfacedObject.
But now, when it becomes time to set my interfaced object .Free, I'm getting EInvalidPointer exceptions.
As a result, I'm beginning to conclude that the word interface means something completely different to a Java developer, and a Delphi developer.
Can someone who is proficient at both languages enlighten me as to the differences?
Cheers.
Interface types in Delphi have three functions:
IInterface
is the same as the COM IUnknown
).These functions are conceptually distinct, and as you have found, produce a less than optimal result when combined in the same feature:
IInterface
/IUnknown
, and as such, have the three IUnknown
methods (AddRef
, Release
and QueryInterface
- the first two are renamed _AddRef
and _Release
in Delphi to discourage you from calling them directly). If you want to be able to query for an interface at runtime, you also need to give it a GUID.TInterfacedObject
exists as a convenient base class, though you don't have to use it if you implement _AddRef
, _Release
and QueryInterface
yourself (doing so involves a standard pattern, so it isn't hard). In principle, you can also disable reference counting by returning -1
for the first two (the TComponent
class does this, for example)._AddRef
and _Release
calls when an object is accessed via an interface. This makes it frequently unsafe to access the same object through an object and interface reference even when _AddRef
and _Release
just return -1
.The difference is in garbage collector. Java has one. But in Delphi you have to control your objects by yourself.
_AddRef and _Release created to make this little easy. When a variable begins to point to your object, Delphi calls _AddRef. There you have to increase counter of references to that object.
When variable in your code "loose" link to object Delphi calls _Release. There you have to decrease counter. When your counter become 0 then you can call destroy() for this object Self.Destroy()
.
Hope this helps.
PS. TInterfacedObject already implements these methods, that is why Google and Delphi documentation advise to use TInterfacedObject.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With