Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2011-01

Casting descendant interface variables to base

6 messages · 2 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

cobines

Hello everyone,

I have attached a program about which I have a question.

Why does iBase have different value than iBaseAsBase? It seems simply assigning to interface variable doesn't change it to base interface, I have to explicitly use "as IBaseInterface". Is it correct?

Basically, I'm trying to determine in CopyToInterface function if the parameter points to the same object as Self.

cobines

Reply by email

Andrew Hall
to cobines

Interfaces do not behave like classes. Each each interface implemented/supported by a class is unique - at runtime a "descendent" interface is entirely unrelated to its ancestor.

Regards Andrew.

cobines wrote 16 lines
Hello everyone, I have attached a program about which I have a question. Why does iBase have different value than iBaseAsBase? It seems simply assigning to interface variable doesn't change it to base interface, I have to explicitly use "as IBaseInterface". Is it correct? Basically, I'm trying to determine in CopyToInterface function if the parameter points to the same object as Self. -- cobines <project1.lpr>_______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

cobines
to Andrew Hall

2011/1/31 Andrew Hall :

Interfaces do not behave like classes.  Each each interface implemented/supported by a class is unique - at runtime a "descendent" interface is entirely unrelated to its ancestor.

Ok, so in this assignment

var
  iBase: IBaseInterface;
  iDesc: IDescInterface;
begin
  iBase             := iDesc;
end;

iBase still holds a pointer to IDescInterface of the class instance, but in this

begin
  iBase             := iDesc as IBaseInterface;
end;

it is now a pointer to IBaseInterface, because of implicit QueryInterface?

So, I think I can compare interface variables but first I have to bring them to the same interface using "as", for example to IUnknown.

cobines

Reply by email

Andrew Hall
to cobines: I have attached a program about which I have a question. Why does iBase have different…

A more detailed answer:

iDesc holds TDescClass as IDescInterface
iBase holds TDescClass as IDescInterface
iBaseAsBase holds TBaseClass as IBaseInterface

iBase holds the IDescInterface interface because they are compile-time compatible (the same as an ancestor object reference holding an object from a descendent class). iBaseAsBase explicitly casts the interface to the iBaseInterface - since the only class which implements this interface is TDescClass's ancestor, this interface reference must be used.

** If your declaration was changed thus: "TBaseClass = class(TInterfacedObject)" then the code would compile (exception for the iSelf assignment) but you would receive an "invalid typecast" at "iBaseAsBase := iBase as IBaseInterface" since TDescClass no longer supports IBaseInterface.

** If your declaration was changed thus: "TDescClass = class(TBaseClass, IBaseInterface, IDescInterface)" then iBaseAsBase would hold TDescClass as IBaseInterface.

iSelf holds TBaseClass as IBaseInterface
iSelfAsBase holds TBaseClass as IBaseInterface
iOtherAsBase holds TBaseClass as IBaseInterface

In all three of these variables, IBaseInterface is required - which is only implemented by TBaseClass - so (as with iBaseAsBase) they all hold the same reference.

An interface reference points to the private data structure which defines that interface and the procedure pointers to its supported methods (for the specific implementing class) - it does not point to the implementing object (Self) - it has no way to access the implementing class structure (or contained fields).

Regards Andrew.

cobines wrote 6 lines
Why does iBase have different value than iBaseAsBase? It seems simply assigning to interface variable doesn't change it to base interface, I have to explicitly use "as IBaseInterface". Is it correct? Basically, I'm trying to determine in CopyToInterface function if the parameter points to the same object as Self.

Reply by email

Andrew Hall
to cobines: 2011/1/31 Andrew Hall : Ok, so in this assignment var iBase: IBaseInterface; iDesc:…
cobines wrote
it is now a pointer to IBaseInterface, because of implicit QueryInterface?

The reference changes because you have explicitly cast (the implementing object) to another interface.

So, I think I can compare interface variables but first I have to bring them to the same interface using "as", for example to IUnknown.

Yes. This function will confirm the two provided interfaces are implemented by the same object...

function EqIntf(a, b: IUnknown): Boolean;
begin
  Result := (a as IUnknown) = (b as IUnknown);
end;

Regards Andrew.

Reply by email