Search code examples
typesd

How to get classinfo of object declared as an interface type


I have a list of some interface type. For debugging, I'd like to print out the name of the underlying class of each object in the list:

import std.stdio, std.container;

interface IFace { }

class Foo : IFace { }
class Bar : IFace { }

unittest {
  SList!IFace list;
  list.insert(new Foo);
  list.insert(new Bar);

  foreach(obj ; list) writeln(obj.classinfo.name);
}

I was hoping for

Foo

Bar

But instead got

IFace

IFace

Is there a way to extract the implementing class from an interface-typed variable at runtime?

Furthermore, I do get the expected result if IFace is a class instead of an interface. Why?


Solution

  • Cast the interface to Object then get the typeid or classinfo:

    foreach(obj ; list) writeln((cast(Object)obj).classinfo.name); 
    

    You should also check for null on the cast to be fully correct, perhaps make a helper function to do this, but if you know for sure all your interfaces do come from Object, you'll be ok for debugging.

    The reason this is needed is that a D interface does not necessarily represent a D object, so the class name might not actually be available. For example, it might be a COM object created in some outside DLL and accessed through an interface. It might be a C++ class that D is talking to. Or more, interfaces are kept generic so they can act as the common.... well, interface between a variety of components written in a variety of languages and styles.

    That's also why the cast to Object might return null: if it is a C++ class, it won't be able to convert back into a D Object.

    Furthermore, I do get the expected result if IFace is a class instead of an interface. Why?

    A class is guaranteed to have a D Object base with run time type info available, so it just works there. An interface can come from other sources.