Let me simplify your example:

type
  TNewClass = class(TInterfacedObject,ISecondDescendant);

var
  First: IFirstDescendant;
  Second: ISecondDescendant;

Second := TNewClass.Create;  // Line 1
First := Second;  // Line 2

The above compiles and works fine.  Line 1 actually performs 2 operations:

1.  o := TNewClass.Create, where o is a temp var of type TNewClass
2.  Second := o

Contrary to popular belief, the second operation does not call
QueryInterface.  Instead, at compile time, the interface reference is bound
to the object reference.  This is because at compile time, the interface
reference is always a known offset from the object reference (see my last
long post).

To see this you can either look at the compiled code, or remove the GUID
from your interface declaration.  Without a GUID, the second operation still
works, whereas, if the second operation was:

Second := o as ISecondDescendent,

without a GUID will raise a compile time error.

Line 2 also works because ISecondDescendent implements all methods of
IFirstDescendents and are therefore assignment compatible.  The important
point here is they are assignment compatible, but they are different.

However, if you do:

First := Second as IFirstDescendent

you will get an exception EIntfCastError.  This is because the "as" operator
calls QueryInterface on Second, and TNewClass does not support
IFirstInterface.

Regards,
Dennis.

----- Original Message -----
From: "Todd Martin" <[EMAIL PROTECTED]>
To: "Multiple recipients of list delphi" <[EMAIL PROTECTED]>
Sent: Monday, June 16, 2003 1:46 PM
Subject: Re: [DUG]: Interface Inheritance


> Hi Guys.
>
> Thanks for all the feedback. I didn't realise it would get so much
response.
> In the end I decided to go with the following :
> IFirstDescendant = interface(IInterface);
> ISecondDescendant = interface(IFirstDescendant);
>
> TNewClass = class(TInterfacedObject,IFirstDescendant ,ISecondDescendant);
>
> However I noticed one very peculiar aspect of interfaces along the way
when
> compiling.
>
> If I define a procedure
> DoSomething(AObject : IFirstDescendant);
> and
> TNewClass = class(TInterfacedObject,ISecondDescendant);
>
> and then the following code compiles okay
>
> procedure Test;
> var
> MyObject : ISecondDescendant;
> begin
>   MyObject := TNewClass.Create;
>   DoSomething(MyObject);
> end;
>
> I haven't checked yet, but I'm assuming the MyObject passed through to
> procedure DoSomething() is then "nil", since TNewClass doesn't support
> IFirstDescendant. Would that be your guess too? So why does it compile? On
> the otherhand, does the ISecondDescendant pointer get sucessfully
converted
> to a IFirstDescendant pointer, in which case, why does
> MyObject.QueryInterface(IFirstDescendant,FirstObject) return a "nil"
pointer
> to FirstObject?
>
> However, if I define
> IFirstDescendant = interface(IInterface);
> ISecondDescendant = interface(IInterface);
>
> ie. no interface inheritance - (or whatever you want to call it)
> and
>
> TNewClass = class(TInterfacedObject,IFirstDescendant,ISecondDescendant);
>
> the Test() procedure does not compile. Any comments?
>
> Thanks.
>
> ----- Original Message -----
> From: "Conor Boyd" <[EMAIL PROTECTED]>
> To: "Multiple recipients of list delphi" <[EMAIL PROTECTED]>
> Sent: Monday, June 16, 2003 10:31 AM
> Subject: RE: [DUG]: Interface Inheritance
>
>
> > There are a lot of people (including me) who never use the term
'interface
> > inheritance'.  You're right, it's not inheritance.
> >
> > As an aside, having had the 'chance' recently to go some VB6 coding
:-( I
> > found the Microsoft documentation utterly misleading when it talks about
> > interface inheritance, when IMO it should be talking about 'interface
> > implementation', which is probably a phrase which is also appropriate to
> > what we're talking about here.
> >
> > Cheers,
> >
> > Conor
> >
> > -----Original Message-----
> > From: Karl Reynolds [mailto:[EMAIL PROTECTED]
> >
> > > So this is one simple case where you have IStream inheriting
> > > from ISequentialStream (see ActiveX.pas) but you are not required
> > > to implement ISequentialStream is you are implementing IStream.
> >
> > Utterly bizarre.  I get your point - that interface "inheritance" has to
> be
> > implemented the way it is in Delphi in order to support such
strangeness.
> > But it's not really inheritance any more, is it.
>
> --------------------------------------------------------------------------
> -
> >     New Zealand Delphi Users group - Delphi List - [EMAIL PROTECTED]
> >                   Website: http://www.delphi.org.nz
> > To UnSub, send email to: [EMAIL PROTECTED]
> > with body of "unsubscribe delphi"
> > Web Archive at: http://www.mail-archive.com/delphi%40delphi.org.nz/
> >
>
>
> --------------------------------------------------------------------------
-
>     New Zealand Delphi Users group - Delphi List - [EMAIL PROTECTED]
>                   Website: http://www.delphi.org.nz
> To UnSub, send email to: [EMAIL PROTECTED]
> with body of "unsubscribe delphi"
> Web Archive at: http://www.mail-archive.com/delphi%40delphi.org.nz/
>
---------------------------------------------------------------------------
    New Zealand Delphi Users group - Delphi List - [EMAIL PROTECTED]
                  Website: http://www.delphi.org.nz
To UnSub, send email to: [EMAIL PROTECTED] 
with body of "unsubscribe delphi"
Web Archive at: http://www.mail-archive.com/delphi%40delphi.org.nz/

Reply via email to