7
votes

Say, classes A1,A2,...,An all extends the abstract class B. I would like A1,...,An to have a function that returns a string of the class name. This is certainly known in compile-time, but I would like to implement this function in B, and use inheritance so that all Ai:s get this functionality.

In java, this can easily be done, by letting B have the method

String getName() {
    return this.getClass();
}

more or less. So, how do I do this in D? Also, is there a way, using traits or similar, to determine which class members are public?

4

4 Answers

5
votes

simply typeof(this).stringof

however this is fixed at compile time so inheritance doesn't change the value

this.typeinfo.name

will give the dynamic name of the classname of the instance

http://www.d-programming-language.org/expression.html#typeidexpression
http://www.d-programming-language.org/phobos/object.html#TypeInfo_Class

3
votes

It is known at compile-time, but evaluating the class name at runtime requires demangling, I think.

Here it is if runtime-evaluation is okay:

import std.stdio;
import std.algorithm;

abstract class B {
    string className() @property {
        return this.classinfo.name.findSplit(".")[2];
    }
}

class A1 : B { }
class A2 : B { }

void main()
{
    auto a1 = new A1();
    writeln(a1.className);

    auto a2 = new A2();
    writeln(a2.className);
}
3
votes

You can get the name of a class simply by using ClassName.stringof.

If you want it as a virtual function then I would recommend using the Curiously Recurring Template Pattern:

class B
{
    abstract string getName();
}

class BImpl(T)
{
    string getName() { return T.stringof; }
}

class A1 : BImpl!A1 { ... }
class A2 : BImpl!A2 { ... }
/+ etc. +/

Unfortunately, at the moment there is no way to determine which class members are public. You can iterate all members by using the allMembers trait.

foreach (member; __traits(allMembers, MyClass))
    writeln(member);
0
votes

Here is what works for me - assuming runtime-evaluation is okay, and you're only interested in the actual class name without the package-path or the module name.

#!/usr/bin/env rdmd

module test;

// test successful with DMD v2.063 (May 2013) through v2.086.0 (May 2019)

class A
{
    public string derivedName() const
    {
        import std.string : lastIndexOf;
        const startIndex = this.classinfo.name.lastIndexOf('.') + 1;
        return this.classinfo.name[startIndex .. $];
    }
}

class B : A
{
}

void main()
{
    auto b = new B();
    assert(b.derivedName == "B");
}