www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Casting from interface to real class?

reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Is it possible to do a dynamic cast from an interface to a real class?

SomeClass k = cast(SomeClass)anInterface;

will that succeed if anInterface started life as a SomeClass?

--bb
Jan 20 2008
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Bill Baxter wrote:
 Is it possible to do a dynamic cast from an interface to a real class?
 
 SomeClass k = cast(SomeClass)anInterface;
 
 will that succeed if anInterface started life as a SomeClass?
I think I found the answer: Yes. http://spottedtiger.tripod.com/D_Language/D_FAQ_XP.html """ Casting from an interface back to the class means subtracting that offset. The subtract is a little tricky since the pointer doesn't know where it came from, so the first entry in the interface's vtbl[] is an instance of the class Interface with the necessary offset. The cast is handled by the library function _d_interface_cast(). """ --bb
Jan 20 2008
parent reply Oliver <oliver.ruebenkoenigREM web.de> writes:
Hi Bill,

Bill Baxter Wrote:

 Bill Baxter wrote:
 Is it possible to do a dynamic cast from an interface to a real class?
 
 SomeClass k = cast(SomeClass)anInterface;
 
 will that succeed if anInterface started life as a SomeClass?
I hope I understood your question correctly, here is an example. -------------------- import std.stdio; interface Expr { Expr type(); void print(); } Expr steSymbol; class Symbol : Expr { public: this(char [] name) { this.itsName = name; } char [] getName() { return this.itsName; } Expr type() {return steSymbol;} void print() {writefln(this.itsName);} private: char [] itsName; int itsInt; } int main ( char [][] arg ) { Expr e; steSymbol = new Symbol("Symbol"); e = new Symbol("x"); steSymbol.print(); e.print(); e.type().print(); Symbol s = cast(Symbol)e; s.print(); writefln((cast(Symbol)e).getName()); return 0; }
Jan 21 2008
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Oliver wrote:
 Hi Bill,
 
 Bill Baxter Wrote:
 
 Bill Baxter wrote:
 Is it possible to do a dynamic cast from an interface to a real class?

 SomeClass k = cast(SomeClass)anInterface;

 will that succeed if anInterface started life as a SomeClass?
I hope I understood your question correctly, here is an example. -------------------- import std.stdio; interface Expr { Expr type(); void print(); } Expr steSymbol; class Symbol : Expr { public: this(char [] name) { this.itsName = name; } char [] getName() { return this.itsName; } Expr type() {return steSymbol;} void print() {writefln(this.itsName);} private: char [] itsName; int itsInt; } int main ( char [][] arg ) { Expr e; steSymbol = new Symbol("Symbol"); e = new Symbol("x"); steSymbol.print(); e.print(); e.type().print(); Symbol s = cast(Symbol)e; s.print(); writefln((cast(Symbol)e).getName()); return 0; }
Yep, that's exactly what I was hoping I could do but thinking I couldn't. But it does work. Happy day. --bb
Jan 21 2008
parent Oliver <oliver.ruebenkoenigREM web.de> writes:
Bill Baxter Wrote:

 Oliver wrote:
 Hi Bill,
 
 Bill Baxter Wrote:
 
 Bill Baxter wrote:
 Is it possible to do a dynamic cast from an interface to a real class?

 SomeClass k = cast(SomeClass)anInterface;

 will that succeed if anInterface started life as a SomeClass?
I hope I understood your question correctly, here is an example. -------------------- import std.stdio; interface Expr { Expr type(); void print(); } Expr steSymbol; class Symbol : Expr { public: this(char [] name) { this.itsName = name; } char [] getName() { return this.itsName; } Expr type() {return steSymbol;} void print() {writefln(this.itsName);} private: char [] itsName; int itsInt; } int main ( char [][] arg ) { Expr e; steSymbol = new Symbol("Symbol"); e = new Symbol("x"); steSymbol.print(); e.print(); e.type().print(); Symbol s = cast(Symbol)e; s.print(); writefln((cast(Symbol)e).getName()); return 0; }
Yep, that's exactly what I was hoping I could do but thinking I couldn't. But it does work. Happy day. --bb
there is one, caveat though. If you overload opEquals you need to cast to object to make that work, which is very ugly in the code. int opEquals( Object o ) { Symbol s = cast(Symbol)o; return s && this.itsName == s.itsName; } and calling looks ugly, something like: assert( cast(Object)e1 == cast(Object)e2 ); I think the problem comes from the fact that interface can also be a COM interface. http://www.digitalmars.com/d/archives/digitalmars/D/Object_and_interface_compatibility_48235.html should you find a way to avoid the cast, i'd be very interested to see that, otherwise happy coding ;-)
Jan 21 2008