Solved

How can i cast interface to class?

Posted on 2000-04-11
11
992 Views
Last Modified: 2012-06-21
Hello,

does anyone know how to cast an object that implements interfaces to its real class type?
For example, if i have the
following class

IFoo = interface
[some GUID]
  procedure Bar;
end;

TFoo = class(TInterfacedObject, IFoo)
  procedure Bar;
end;

i can cast TFoo to IFoo with As:

Foo := TFoo.Create
(Foo As IFoo).Bar

But if i say

(Foo as TFoo).Bar

i get the compiler-error:

Operation not applicable to this operand type.

I need this for using a class with TList.IndexOf. If i have for
example

IBar = interface
...

IFoo = interface
  function GetBar: IBar;
  procedure SetBar(Bar: IBar);
  property Bar: IBar read GetBar write SetBar;
end;


TFoo = class(TInterfacedObject, IFoo)
...


and there is a method of TFoo, where i have to search for a bar, and
i use the interface -- it fails

Foo := TFoo.Create;

Somelist.IndexOf(Foo.Bar)  // doesnt find anything

So i would need the real class type of Bar. My first attempt was to
do an unchecked cast (which the compiler gladly accepts):

...
var
SomeBar: TBar

...
SomeBar := TBar(Foo.Bar);
Somelist.IndexOf(SomeBar);

but this fails.

What to do?

Chris

 
0
Comment
Question by:hec08036
  • 4
  • 3
  • 2
  • +2
11 Comments
 
LVL 13

Expert Comment

by:Epsylon
ID: 2703808
How did you define the variable Foo? I get no compiler errors when I do this:

var Foo: TObject;

(Foo as TFoo).Bar;
0
 
LVL 10

Expert Comment

by:Lischke
ID: 2703814
Hi Chis,

the unchecked type cast as you did above is the way you would usually "convert" an interface to a class (if the class implements this interface, of course). The reason why this works is that the class is just a pointer as well as the interface and both point to the same memory. The other way around with the "as" operator could also be done using an unchecked type cast but with the "as" operator there is an implicit reference count increment and a "type" checking involved (read: whether the class actually implements the interface).

Another point is that properties are not allowed in interfaces. So I don't know why the compiler accepts your Bar/SetBar/GetBar construct.

You have not shown the declaration of TBar but I assume it's:

TBar = class(TInterfacedObject, IBar)
  :
end;

In this case you should be able to cast an IBar to a TBar without problems. YOu can check this with a private variable of TBar. Create an instance, pass it around as IBar, cast it back to TBar and see if the private variable contains a value you have set before.

If all fails you can try another approach. Store the interfaces in the list instead of the classes. Actually it's the same pointer as I already wrote but the compiler might handle this situation different.

Ciao, Mike
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 2706055
Mike: A correction. An interface CAN define a property, but it can't store anything. Note that that both set and get accessors are defined - the implementor of the interface stores the property value and provides access to it through those accessor methods inthe interface.

Chris: Calling Bar in Foo is done by Foo.Bar as you have already tried - there is no casting required to call it. The fact that it fails suggests your Bar method is wrong rather than the interface mechanism :-)

Cheers,

Raymond.
0
 
LVL 20

Accepted Solution

by:
Madshi earned 100 total points
ID: 2706668
Hi friends,

Raymond is right, an interface CAN have properties, no problem there.

But Ray, Chris wants to get the TBar object pointer from the IBar interface pointer he got from "Foo.Bar". THAT'S the problem.

Mike, I'm sorry, but it's not allowed to simply typecast interfaces to objects. That's a strictly NO NO - otherwise you'll get exceptions. Try this code:

type
  ITest = interface
  end;
  TITest = class (TInterfacedObject, ITest)
  end;

var tit : TITest;
    it  : ITest;
initialization
  tit := TITest.Create;
  it := tit;
  if pointer(tit) = pointer(it) then
    beep;

The pointers are NOT identical!!

Chris, I'm solving this problem usually by adding a "GetSelfAsTObject" method to my base interface, that does nothing but this:

type
  IMyBaseInterface = interface
    function GetSelfAsTObject : TObject;
  end;
  TIMyBaseInterface = class (TInterfacedObject, IMyBaseInterface)
    function GetSelfAsTObject : TObject;
  end;

function TIMyBaseInterface.GetSelfAsTObject : TObject
begin
  result := self;
end;

Regards, Madshi.
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 2706690
Hi Madshi,

Bar is just a method in the interface, it doesn't represent the actual interface, so it is meaningless to attempt to get the object instance just given bar alone.

I also don't see the point of the GetSelfAsObject method. Isn't self defined in the implemented methods from the interface?

Maybe I'm missing something... :-)

Cheers,

Raymond.
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 20

Expert Comment

by:Madshi
ID: 2706724
:-)

Well, the Bar property gives us an IBar instance. This IBar instance is implemented by an unknown object - let's say a TIBar object. Now Chris has stored all TIBar objects in a TList (not the IBar instances!!). How can he find out which list index belongs to that IBar instance? Only by getting the object pointer of the object that implements the IBar instance that we get from the Bar method. Right?
Of course "self" is defined in the methods of that interface (that's how my GetSelfAsTObject method works).
But he needs to know the implementing object from OUTSIDE the methods!!
Tell me: If we have this:

var aBar : IBar;
    aBarObj : TIBar;
begin
  aBar := OtherInterface.GetBar;
  aBarObj := ????

How do you get the aBarObj that belongs to aBar? That's Chris' question. And the only answer I know is to add a method to the IBar interface. Then you can do this:

  aBarObj := aBar.GetSelfAsTObject as TIBar;

Regards, Madshi.
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 2706745
DOH! I was looking at the first code sample where Bar is just a procedure... I see where GetSelfAsObject comes into it...

BTW, isn't the Bar property superfluous (ie: You can use GetInterface to do the same..)

Cheers,

Raymond.

PS: There are a couple of good articles in the last month on interfaces on community.borland.com...
0
 
LVL 20

Expert Comment

by:Madshi
ID: 2706752
>> BTW, isn't the Bar property superfluous (ie: You can use GetInterface to do the same..)

No, you can't. GetInterface only gives you the interfaces that are directly implemented in the class. Then TFoo had to look like this:

type
  TFoo = class (TInterfacedObject, IFoo, IBar)

THEN you could use GetInterface to get an IBar instance.

Regards, Madshi.
0
 
LVL 10

Expert Comment

by:Lischke
ID: 2706840
Hi guys,

wow, it's been quite busy here since yesterday :-) Madshi, thank you for the correction, I'm obviously wrong (although I was so sure about the same pointer thing, where did I get this idea from ....?). Now I finally understand your GetSelfAsTObject :-)

Ciao, Mike
0
 
LVL 20

Expert Comment

by:Madshi
ID: 2706861
=:-D
0
 

Author Comment

by:hec08036
ID: 2707599
Thanks a lot! Now it works.

Best Regards

Chris
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now