The simplest form of reflection available in D is runtime type information, which is available through the typeid()
operator. It is used extensively by the druntime
implementation and is integral to the safe dynamic casting of classes.
Let's execute the following steps to get dynamic runtime type information:
typeid(variable_or_type)
.Object
, check for null
, and then use typeid(the_casted_object)
.The code is as follows:
TypeInfo typeInfoAboutInt = typeid(int); typeInfoAboutInt = typeid(1); // also works
The compiler and the runtime library automatically define type information for all types. This information is found in static TypeInfo
objects, which is retrieved by reference using the typeid()
operator. The definition of the TypeInfo
interface is found in the automatically-imported object.d
module of druntime, and thus it is always available to D programs.
TypeInfo
is tailored for druntime's needs. It contains functions for:
new
operator and built-in array operators)., typeid(int*).next is typeid(int)
. typeid(int*)
gives information about a pointer, which points to the next type.Classes and interfaces have to get additional functions:
These methods are vital to the proper functioning of classes. They enable safe dynamic casting from base class to derived class, proper object construction, and automatic implementation of toString
, which works without being explicitly overridden in every class you write.
The TypeInfo
references are only stored with the data of class objects (specifically, the first hidden virtual function entry for each object stores a reference to the correct TypeInfo
reference). With all other types, typeid
yields a reference based on the static type. This means that you cannot retrieve the runtime type information from a void*
or void[]
, as shown in the following code:
void main() { int[] a; arrayType(a); } void arrayType(void[] arr) { // assert(typeid(arr) == typeid(int[])); // FAILS // The following passes because non-class typeid is based on static type assert(typeid(arr) == typeid(void[])); }
If you want to work with void*
in a type-safe way, it is important to explicitly pair a TypeInfo
object with it. This is how the druntime functions work, also some of the language features' non-template D variadic functions work in the same way.
Templates are generally better at both type safety and efficiency than runtime information. You should only use TypeInfo
based typing in functions when you have special ABI requirements. The void*
and TypeInfo
pairs are used in druntime primarily for legacy reasons; the library was designed before D had templates.
Static types are also used with interfaces: typeid(some_object_via_interface)
and is typeid(the_interface_you_are_using);
. In order to get the dynamic type of the object behind the interface, you will have to first cast it to an object, and then cast it from the object to the derived class.
To compare types at runtime, you may use either the ==
operator or the is
operator on TypeInfo
. Since there's only one instantiation for each type, you can always rely on the comparison operators.
TypeInfo
's members at http://dlang.org/phobos/object.html#TypeInfo . Also, scroll down to TypeInfo_Class
to see additional members available on classes.3.137.186.178