I fell in an easy trap in my understanding of Delphi interfaces but it took so long before i realized this.
The trap was to consider interfaces as C++ pure virtual abstract classes. To be more precise i thought that, in Delphi, adding interfaces to a class declaration was a kind of multiple inheritance, but in a restricted way. In fact, Delphi let you to "multiple" inherits only with interfaces, preventing all the possible headaches that true "multiple inheritance" involves.
Something like ...
IUnknown = class public function QueryInterface(const iid: TIID; var obj): HResult; virtual; abstract; function AddRef: Longint; virtual; abstract; function Release: Longint; virtual; abstract; end;
I try to clarify this with an example
Take a simple Delphi type declaration
type IAInterface = interface(IUnknown) procedure AMethod; end; IBInterface = interface(IAInterface) procedure BMethod; end; ICInterface = interface(IAInterface) procedure BMethod; procedure CMethod; end; type TFoo = class(TObject,IBInterface) protected function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; private procedure BMethod; public procedure AMethod; end; TBar = class(TFoo,ICInterface,IBInterface) private procedure IBInterface.AMethod = ADifferentMethod; procedure IBInterface.BMethod = BMethod; procedure ICInterface.BMethod = BSecondMethod; procedure ADifferentMethod; procedure BSecondMethod; public procedure CMethod; end;
this is what wrongly i try to model in my mind
///////////////////////////////////////////////////////////////////////////// // interface: public ///////////////////////////////////////////////////////////////////////////// class IAInterface : virtual public __IInterface { public: virtual void AMethod() = 0; }; class IBInterface : virtual public IAInterface { public: virtual void BMethod() = 0; }; class ICInterface : virtual public IAInterface { public: virtual void BMethod() = 0; virtual void CMethod() = 0; }; //--------------------------------------------------------------------------- class _IFoo : virtual public __IInterface { public: virtual void AMethod() = 0; // public in IntSight.pas }; class _IFooType : virtual public _IFoo, virtual public IBInterface {}; //--------------------------------------------------------------------------- class _IBar : virtual public _IFooType { public: virtual void CMethod() = 0; }; class _IBarType : virtual public _IBar, virtual public ICInterface {}; ///////////////////////////////////////////////////////////////////////////// // implementation interface: protected ///////////////////////////////////////////////////////////////////////////// //--------------------------------------------------------------------------- class TFoo : protected __TObject, virtual public _IFooType { protected: virtual void AMethod() {}; virtual void BMethod() {}; }; //--------------------------------------------------------------------------- class TBar : protected TFoo, virtual public _IBarType { protected: virtual void AMethod() {}; virtual void CMethod() {}; virtual void BMethod() { return TFoo::BMethod(); }; //single impl? }; //---------------------------------------------------------------------------
As you surely notice, there are a lot of errors in this sight. Enjoy this first list:
In Delphi, declaring a type
TBar = class(TFoo,ICInterface,IBInterface)
DOES NOT MEAN that you are introducing a new type that is multiple
inherited from TFoo, ICInterface, IBInterface in any way!
There's nothing similar to
class _IFoo : virtual public __IInterface { public: virtual void AMethod() = 0; // public in IntSight.pas }; class _IFooType : virtual public _IFoo, virtual public IBInterface {}; class _IBar : virtual public _IFooType { public: virtual void CMethod() = 0; }; class _IBarType : virtual public _IBar, virtual public ICInterface {};
The semantic of the Delphi declaration can be described saying that what is introduced by this type declaration are:
a new class type "TBar" single inherited from "TFoo" as usual
a new group of cast operator, (functions from a type to another type), that let you cast from objects of type TBar to the declared interfaces. This group of cast operators are added to the inherited ones, able to transform a TFoo in the inherited interfaces.
function TBar.cast1: TBar => ICInterface
function TBar.cast2: TBar => IBInterface
function TFoo.cast1: TFoo => IBInterface or whatever else in declared in inheritance
and of course, you can always cast a object reference from a derived class to a reference of a object of a base class ...
But there is a big difference from upcast to a base class and casting to an interface, in fact a derived class cannot remove methods from the (public) part of his base class, while it can implement interface methods with private ones.
Interface methods can also implemented by methods with a different name, and this can be used to resolve name conflicts between interfaces.
(forgetting for a while, one great feature of Delphi: the "implements" keyword...)
So consider public class declaration as a kind of interface that can be merged with other interfaces in a multiple inherited type cannot work!
This code is still wrong, but at least it tries to consider this fact
///////////////////////////////////////////////////////////////////////////// // interface: public ///////////////////////////////////////////////////////////////////////////// class IAInterface : virtual public __IInterface { public: virtual void AMethod() = 0; }; class IBInterface : virtual public IAInterface { public: virtual void BMethod() = 0; }; class ICInterface : virtual public IAInterface { public: virtual void BMethod() = 0; virtual void CMethod() = 0; }; ///////////////////////////////////////////////////////////////////////////// // implementation: public ///////////////////////////////////////////////////////////////////////////// class TFoo : public __TObject { protected: class _IBInterface: virtual public IBInterface { private: TFoo* FOwner; public: virtual void BMethod() { return FOwner->BMethod(); }; virtual void AMethod() { return FOwner->AMethod(); }; _IBInterface(TFoo* AOwner) : FOwner(AOwner) {}; }; friend class TFoo::_IBInterface; _IBInterface* FIBInterface; public: TFoo() : __TObject() { FIBInterface = new _IBInterface(this); }; ~TFoo() { delete FIBInterface; }; operator IBInterface& () { return *static_cast(FIBInterface); } //--------------------------------------------------------------------------- protected: virtual void BMethod() {}; //no private... public: virtual void AMethod() {}; }; //--------------------------------------------------------------------------- class TBar : public TFoo { protected: class _ICInterface: virtual public ICInterface { private: TBar* FOwner; _ICInterface(TBar* AOwner) : FOwner(AOwner) {}; public: virtual void BMethod() { return FOwner->BSecondMethod(); }; virtual void CMethod() { return FOwner->CMethod(); }; virtual void AMethod() { return (static_cast ( (*static_cast (FOwner)))).AMethod(); }; friend class TBar; }; friend class TBar::_ICInterface; _ICInterface* FICInterface; //--------------------------- class _IBInterface: virtual public IBInterface { private: TBar* FOwner; _IBInterface(TBar* AOwner) : FOwner(AOwner) {}; public: virtual void BMethod() { return FOwner->BMethod(); }; virtual void AMethod() { return FOwner->ADifferentMethod(); }; friend class TBar; }; friend class TBar::_IBInterface; _IBInterface* FIBInterface; public: TBar() : TFoo() { FIBInterface = new _IBInterface(this); FICInterface = new _ICInterface(this); }; ~TBar() { delete FIBInterface; delete FICInterface; }; operator ICInterface& () { return *static_cast (FICInterface); } operator IBInterface& () { return *static_cast (FIBInterface); } //--------------------------------------------------------------------------- private: virtual void ADifferentMethod() {}; virtual void BSecondMethod() {}; public: virtual void CMethod() {}; }; //---------------------------------------------------------------------------
Why this code is wrong?
There are still many errors, as you may see in the next section, but one thing should be noted here:
Delphi interface inheritance (as COM does) is NOT "virtual". This means that in this declaration
type IAInterface = interface(IUnknown) procedure AMethod; end; IBInterface = interface(IAInterface) procedure BMethod; end; ICInterface = interface(IAInterface) procedure BMethod; procedure CMethod; end;
the common base interface IAInterface is NOT shared between IBInterface and ICInterface (as virtual inheritance would require) but
IBInterface.AMethod and
ICInterface.AMethod
are two different methods that could have different implementations.
This is however not mandatory, and providing only one AMethod in the implementing class, makes this method bound to both interfaces by default.
Call it "weak virtual inheritance" if you like ...
Next | Up.. |