Thread overview
Casting from interface to real class?
Jan 21, 2008
Bill Baxter
Jan 21, 2008
Bill Baxter
Jan 21, 2008
Oliver
Jan 21, 2008
Bill Baxter
Jan 21, 2008
Oliver
January 21, 2008
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
January 21, 2008
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
January 21, 2008
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;
}


January 21, 2008
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
January 21, 2008
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 ;-)