Is there a keyword to access the base class

Steven Schveighoffer schveiguy at yahoo.com
Thu Jun 20 05:32:23 PDT 2013


On Wed, 19 Jun 2013 19:10:39 -0400, Stephen Jones <siwenjo at gmail.com>  
wrote:

>> Hm... would be a nice idiom to implement generically in D.  Like a type  
>> switch.
>>
>> -Steve
>
> That is what I would prefer, but I tried:
>
> writeln(to!(typeof(bars[1]))(bars[1]).val);	
>
> to see if I could access the "DERIVED" (thanks) class type but even  
> though bars[1] is initialized as a new Foos its type is still marked as  
> Bar. So the question is, how do you find the derived class type when  
> presented with only the super class?

You have to understand, D is statically typed.  There are two types  
involved here, the dynamic, object-oriented type, which is only known at  
runtime, and the static type which is known by the compiler.

typeof(bars[1]) gets the *static* type, or the type that the compiler  
knows.  bars is a Bar[], so the compiler only knows that bars[1] is a Bar.

The dynamic type of bars[1], as we know, is Foos.  And bars[1] knows it  
too, but in order to call a function on a derived type, the *compiler* has  
to know it.  So when you say something like:

if(auto der = cast(Foos)bars[1])

You are telling the compiler:

"OK, I know this is a Bar right now, but check during runtime to see if  
this is actually a Foos.  If it is, branch in here with 'der' as a  
variable which is statically typed as Foos."

Then the compiler can know inside that branch, that it can access bars[1]  
via the static type Foos, and you have access to all Foos' members.  Note  
that if the instance is actually a derivative of Foos, the compiler STILL  
will go into that branch!

The "correct" way to do this is to define what you are looking for as a  
virtual or abstract method on the base class/interface, and then the  
compiler does all this work for you (but it's only a vtable lookup, so  
it's much faster).

But if you DON'T know that all derivatives will support 'val' (and you  
have to know this when the base class is written), then you have to do  
this casting dance.

Dynamically typed languages make this easier, but it comes at a price.   
Statically typed languages have the compiler check so much more at compile  
time, so it's much more difficult to make a mistake.  I deal with this all  
the time on PHP, where you can simply type a variable name wrong, and the  
compiler (and sometimes during runtime) won't complain, it just thinks you  
are declaring a new variable on an object instance.

Note that Ali's suggestion of typeid does NOT give you a static type of  
the most derived type, it's a runtime type information object that has  
limited capability.  It's like reflection in Java or .Net.  But much less  
powerful, since D's TypeInfo does not provide a full mapping of members  
that is able to call methods and whatnot.

So while typeid can tell you what the type is (good for comparing, etc),  
you can't call methods on it (well, there are a couple, like comparing two  
objects, but not arbitrary ones).

-Steve


More information about the Digitalmars-d-learn mailing list