Explicit interface implementations solved for Delphi 8
published: Sat, 17-Jan-2004 | updated: Thu, 27-Oct-2005
A few days ago I was trying to solve a particular problem with Delphi 8 that was somewhat easy in C#: implementing interfaces explicitly. (You can read about it here.)
It turns out that I was almost there, but wasn't seeing or making the final step. A reader from Russia (Arioch), whom I understand is not even a Delphi programmer (do I have egg on my face, or what? <g>), made a couple of suggestions to try and solve the problem, one of which worked beautifully.
Here's the suggestion tnat worked, which I've converted into a small test app.
program Test;
{$apptype console}
uses
System.Collections;
type
Foo = class(TObject, ICloneable)
private
protected
function i_Clone : TObject;
public
// implement ICloneable
function ICloneable.Clone = i_Clone;
// the Clone we really want
function Clone : Foo;
end;
function Foo.i_Clone : TObject;
begin
Console.WriteLine('Enter i_Clone');
Result := Clone;
Console.WriteLine('Leave i_Clone');
end;
function Foo.Clone : Foo;
begin
Console.WriteLine('Enter Clone');
Result := Foo.Create;
Console.WriteLine('Leave Clone');
end;
var
f : Foo;
f2 : Foo;
f3 : Foo;
begin
Console.WriteLine('Create a Foo');
f := Foo.Create;
Console.WriteLine('Clone the Foo directly');
f2 := f.Clone;
Console.WriteLine('Cast the Foo to an ICloneable instance, then clone it');
f3 := Foo(ICloneable(f).Clone);
end.
The thing to notice here is that the ICloneable.Clone method is pointing directly to a protected method with the right signature, but with a different name. My previous attempts tried to point the ICloneable.Clone method to another method called Clone, which messed me up with method overload errors. (By the way, I know that Clone isn't really cloning anything, the code is there just to make sure the test app compiles.)
The result of running the app is what we'd expect:
C:\TestApps>test Create a Foo Clone the Foo directly Enter Clone Leave Clone Cast the Foo to an ICloneable instance, then clone it Enter i_Clone Enter Clone Leave Clone Leave i_Clone
As you can see, this solution gives me the effect I wanted: a class that implements an interface, and a way of 'hiding' the interface's non-type-safe methods in favor of type-safe versions. Thanks, Arioch!
