A function that returns the class name in D

Say the classes A1, A2, ..., An all extend 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 at 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 is easy to do if B has a 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 members of the class are publicly available?

+7
source share
4 answers

just typeof(this).stringof

however, this is fixed at compile time, so inheritance does not change the value

 this.typeinfo.name 

will give a dynamic name to the instance class name

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

+5
source

This is known at compile time, but, in my opinion, evaluating a class name at runtime requires damping.

Here, if the runtime estimate is ok:

 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
source

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

If you want this to be a virtual function, 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 members of the class are publicly available. You can iterate all members using allMembers trait .

 foreach (member; __traits(allMembers, MyClass)) writeln(member); 
+3
source

Here's what works for me - assuming the runtime estimation is okay, and you are only interested in the actual class name without the package path or 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"); } 
0
source

Source: https://habr.com/ru/post/891146/


All Articles