Partially Reimplementing / Overriding Interface Implementation
Žarko Gajić
Žarko Gajić
[SHOWTOGROUPS=4,20]
Partially Reimplementing / Overriding Interface Implementation
Žarko Gajić
In Delphi, the reserved word “interface” has two distinct meanings. In a Delphi unit, “interface” denotes the start of a unit section used to declare public constants, data types, variables, procedures and functions visible and accessible to other units using this unit. In OOP jargon, an “object interface” or simply “interface” is a kind of a class with no implementation (but not like a class with abstract methods). An interface defines methods that can be implemented by a class (a class “implements” the interface). Object interfaces might be used when multiple inheritance is needed, and are frequently used when working with COM objects. For some intro to interfaces: Для просмотра ссылки Войдиили Зарегистрируйся.
In recent days I’ve been playing with some COM objects (developed in C++, consuming in my Delphi application) exposing properties (and methods) of interface type.
In some pseudo code, that would look like:
Some properties are declared as read/write – allowing the consumer (me) of the object to reimplement that property’s implementation. Since the property IProperty has a setter and is of IInterfaceProperty type – reimplementing what it does is rather simple: create a Delphi class implementing IInterfaceProperty and set it for the IProperty of the object. When creating my reimplementing class, store the reference to the original IProperty implementation and when there’s no need to override a particular method – just call the original method in my “overridden” method. Case closed
The “problem” I encountered is: IInterfaceProperty has tons of methods and my custom IInterfaceProperty implementing class must implement all of them (even if I would just call the original method implementation) – while I need to override only a few. Hence the idea for this post:
How to Partially Override Interface Implementation
Ok, let’s try to create a simple setup as above. (Hint: noting with interfaces is simple)
The IInterfaceProperty will be IMyInterface and defines a bunch of functions, for the sake of simplicity, something like:
And then we have a class implementing that interface and exposing the interface implementation via a read/write property:
Here’s the implementation part:
So, when the object of TMyClass is created the constructor assigns to fMyInterface an instance of a class actually internally implementing the interface methods:
If you look inside Delphi help, that’s called “implementing interfaces by delegation – delegating to an interface-type property”.
Ok, so far all set. Here’s a simple test to prove this all works:
The output would be:
Now, what I want is to reimplement what my.MyInterface methods do. As stated above, the direct approach is to create a class implementing IMyInterface and assign it to my.MyInterface, like in:
The implementation is whatever we want:
To use my reimplementing class I would do:
nd the output would be
Now, that’s all great and works as expected – however, I need to override just a few methods. My TMyPlus100Class must implement all functions F1 … FN while mostly all I will do is to return the original value and only for some methods I would return something else.
So, the idea is to have a reimplemnting class store the original implementation as a property by delegation and try to “override” just one method (say “F1):
This looks ok, and compiles, but once used:
he output would be
Nothing happened!! My TMyPlus200Class did nothing. That's actually to expect, as if you read the Help: If the delegate property is of a class type, that class and its ancestors are searched for methods implementing the specified interface before the enclosing class and its ancestors are searched.
If I try to use something called “method resolutions for interface”, like:
The above does not compile with : [dcc32 Error] E2264 Cannot have method resolutions for interface 'IMyInterface'
So, what now? Well, let’s introduce another class with a derived class and method resolution, as in:
Note: IOriginal is a private property of TMyPlus300Class, TMyPlus300ClassImplementator extends TMyPlus300Class and uses method resolution to specify what method actually implements the IMyInterface's F1 method.
With implementation:
When pushing my partial re-implementation I just need to make sure I create an instance of TMyPlus300ClassImplementator (and NOT TMyPlus300Class), as in:
And the output:
Voila! Just re-implemented the interface implementation partially: only one method returns a different result compared to original implementation.
p.s.
If you are still reading: bravo. I got lost of all the interface this implementation that
p.s.2
Disclaimer: I'm not freeing any objects above, yes I know.
[/SHOWTOGROUPS]
Partially Reimplementing / Overriding Interface Implementation
Žarko Gajić
In Delphi, the reserved word “interface” has two distinct meanings. In a Delphi unit, “interface” denotes the start of a unit section used to declare public constants, data types, variables, procedures and functions visible and accessible to other units using this unit. In OOP jargon, an “object interface” or simply “interface” is a kind of a class with no implementation (but not like a class with abstract methods). An interface defines methods that can be implemented by a class (a class “implements” the interface). Object interfaces might be used when multiple inheritance is needed, and are frequently used when working with COM objects. For some intro to interfaces: Для просмотра ссылки Войди
In recent days I’ve been playing with some COM objects (developed in C++, consuming in my Delphi application) exposing properties (and methods) of interface type.
In some pseudo code, that would look like:
Код:
anObject : ISomeObject; //has a property IProperty of IInterfaceProperty type
objProperty : IInterfaceProperty
...
objProperty := anObject.IProperty
objProperty.DoSomething;
//or
anObject.IProperty.DoSomething;
Some properties are declared as read/write – allowing the consumer (me) of the object to reimplement that property’s implementation. Since the property IProperty has a setter and is of IInterfaceProperty type – reimplementing what it does is rather simple: create a Delphi class implementing IInterfaceProperty and set it for the IProperty of the object. When creating my reimplementing class, store the reference to the original IProperty implementation and when there’s no need to override a particular method – just call the original method in my “overridden” method. Case closed
The “problem” I encountered is: IInterfaceProperty has tons of methods and my custom IInterfaceProperty implementing class must implement all of them (even if I would just call the original method implementation) – while I need to override only a few. Hence the idea for this post:
How to Partially Override Interface Implementation
Ok, let’s try to create a simple setup as above. (Hint: noting with interfaces is simple)
The IInterfaceProperty will be IMyInterface and defines a bunch of functions, for the sake of simplicity, something like:
Код:
type
IMyInterface = interface(IInterface)
function F1 : integer;
function F2 : integer;
//and many more...
//function F3 : integer;
//function F4 : integer;
//function F5 : integer;
//..
//function FN : integer;
end;
And then we have a class implementing that interface and exposing the interface implementation via a read/write property:
Код:
TMyClass = class(TInterfacedObject, IMyInterface)
strict private
type TMyInterfaceImpl = class(TInterfacedObject, IMyInterface)
function F1 : integer;
function F2 : integer;
end;
private
fMyInterface: IMyInterface;
public
property MyInterface : IMyInterface read fMyInterface write fMyInterface implements IMyInterface;
function MinusF1 : integer;
constructor Create();
end;
Here’s the implementation part:
Код:
constructor TMyClass.Create;
begin
inherited;
fMyInterface := TMyInterfaceImpl.Create;
end;
function TMyClass.MinusF1: integer;
begin
result := -1 * self.MyInterface.F1;
end;
So, when the object of TMyClass is created the constructor assigns to fMyInterface an instance of a class actually internally implementing the interface methods:
Код:
function TMyClass.TMyInterfaceImpl.F1: integer;
begin
result := 1;
end;
function TMyClass.TMyInterfaceImpl.F2: integer;
begin
result := 2;
end;
If you look inside Delphi help, that’s called “implementing interfaces by delegation – delegating to an interface-type property”.
Ok, so far all set. Here’s a simple test to prove this all works:
Код:
var
my : TMyClass;
begin
my := TMyClass.Create;
Writeln ('F1: ' + my.MyInterface.F1.ToString);
Writeln ('F2: ' + my.MyInterface.F2.ToString);
Writeln('-F1: ' + my.MinusF1.ToString);
end;
The output would be:
F1: 1
F2: 2
-F1: -1
Now, what I want is to reimplement what my.MyInterface methods do. As stated above, the direct approach is to create a class implementing IMyInterface and assign it to my.MyInterface, like in:
Код:
TMyPlus100Class = class(TInterfacedObject, IMyInterface)
private
fIOriginal: IMyInterface;
public
constructor Create(const original : IMyInterface);
//must implement all IMyInterface methods
function F1: integer;
function F2: integer;
//…
// function FN: integer;
end;
The implementation is whatever we want:
Код:
constructor TMyPlus100Class.Create(const original : IMyInterface);
begin
self.fIOriginal := original;
end;
function TMyPlus100Class.F1: integer;
begin
//add 100 to original result – so like override method implementation
result := 100 + fIOriginal.F1;
end;
function TMyPlus100Class.F2: integer;
begin
//just return original value
result := fIOriginal.F2;
end;
To use my reimplementing class I would do:
Код:
my := TMyClass.Create;
my.MyInterface := TMyPlus100Class.Create(my);
Writeln ('Plus100 F1:' + my.MyInterface.F1.ToString);
Writeln ('Plus100 F2:' + my.MyInterface.F2.ToString);
Writeln ('Plus100 -F1: ' + my.MinusF1.ToString);
nd the output would be
Plus100 F1:101
Plus100 F2:2
Plus100 -F1: -101
Now, that’s all great and works as expected – however, I need to override just a few methods. My TMyPlus100Class must implement all functions F1 … FN while mostly all I will do is to return the original value and only for some methods I would return something else.
So, the idea is to have a reimplemnting class store the original implementation as a property by delegation and try to “override” just one method (say “F1):
Код:
TMyPlus200Class = class(TInterfacedObject, IMyInterface)
private
fIOriginal: IMyInterface;
property IOriginal : IMyInterface read fIOriginal implements IMyInterface;
public
constructor Create(const original : IMyInterface);
//override just F1
function F1: integer;
end;
function TMyPlus200Class.F1: integer;
begin
result := 200 + fIOriginal.F1;
end;
This looks ok, and compiles, but once used:
Код:
my := TMyClass.Create;
my.MyInterface := TMyPlus200Class.Create(my);
Writeln ('Plus200 F1:' + my.MyInterface.F1.ToString);
Writeln ('Plus200 F2:' + my.MyInterface.F2.ToString);
Writeln ('Plus200 -F1: ' + my.MinusF1.ToString);
he output would be
Plus200 F1:1
Plus200 F2:2
Plus200 -F1: -1
Nothing happened!! My TMyPlus200Class did nothing. That's actually to expect, as if you read the Help: If the delegate property is of a class type, that class and its ancestors are searched for methods implementing the specified interface before the enclosing class and its ancestors are searched.
If I try to use something called “method resolutions for interface”, like:
Код:
TMyPlus200Class = class(TInterfacedObject, IMyInterface)
private
fIOriginal: IMyInterface;
property IOriginal : IMyInterface read fIOriginal implements IMyInterface;
public
constructor Create(const original : IMyInterface);
function F1: integer;
function IMyInterface.F1 = F1; //<- Please use my F1 as an override for IOriginal.F1
end;
The above does not compile with : [dcc32 Error] E2264 Cannot have method resolutions for interface 'IMyInterface'
So, what now? Well, let’s introduce another class with a derived class and method resolution, as in:
Код:
TMyPlus300Class = class(TInterfacedObject, IMyInterface)
private
fIOriginal: IMyInterface;
property IOriginal : IMyInterface read fIOriginal implements IMyInterface;
public
constructor Create(const original : IMyInterface);
function _F1: integer;
end;
TMyPlus300ClassImplementator = class(TMyPlus300Class, IMyInterface)
public
function IMyInterface.F1 = _F1;
end;
Note: IOriginal is a private property of TMyPlus300Class, TMyPlus300ClassImplementator extends TMyPlus300Class and uses method resolution to specify what method actually implements the IMyInterface's F1 method.
With implementation:
Код:
constructor TMyPlus300Class.Create(const original: IMyInterface);
begin
self.fIOriginal := original;
end;
function TMyPlus300Class._F1: integer;
begin
result := 300 + self.IOriginal.F1;
end;
When pushing my partial re-implementation I just need to make sure I create an instance of TMyPlus300ClassImplementator (and NOT TMyPlus300Class), as in:
Код:
my := TMyClass.Create;
my.MyInterface := TMyPlus300ClassImplementator.Create(my);
Writeln ('Plus300 F1:' + my.MyInterface.F1.ToString);
Writeln ('Plus300 F2:' + my.MyInterface.F2.ToString);
Writeln ('Plus300 -F1: ' + my.MinusF1.ToString);
And the output:
Plus300 F1:301
Plus300 F2:2
Plus300 -F1: -301
Voila! Just re-implemented the interface implementation partially: only one method returns a different result compared to original implementation.
p.s.
If you are still reading: bravo. I got lost of all the interface this implementation that
p.s.2
Disclaimer: I'm not freeing any objects above, yes I know.
[/SHOWTOGROUPS]