spierepf
spierepf

Reputation: 2924

Compare and contrast interfaces in Java and Delphi

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.

Upvotes: 6

Views: 974

Answers (2)

Chris Rolliston
Chris Rolliston

Reputation: 4808

Interface types in Delphi have three functions:

  1. Be a general language feature for abstracting interface from implementation a la interface types in Java.
  2. Form the core of Delphi's COM support (a Delphi IInterface is the same as the COM IUnknown).
  3. Provide a form of automated memory management in the context of a non-garbage collected environment.

These functions are conceptually distinct, and as you have found, produce a less than optimal result when combined in the same feature:

  • Every interface in Delphi must ultimately descend from 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).
  • Nonetheless, the compiler will always insert _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.

Upvotes: 8

Nicolai
Nicolai

Reputation: 5797

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.

Upvotes: 3

Related Questions