Функция, которая возвращает имя класса в D - PullRequest
7 голосов
/ 22 июня 2011

Скажем, классы A1, A2, ..., An расширяют абстрактный класс B. Я бы хотел, чтобы A1, ..., An имели функцию, которая возвращает строку с именем класса.Это, конечно, известно во время компиляции, но я хотел бы реализовать эту функцию в B и использовать наследование, чтобы все Ai: s получали эту функциональность.

В Java это можно легко сделать, позволивВ методе

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

более или менее.Итак, как мне сделать это в D?Кроме того, есть ли способ, используя черты или подобное, определить, какие члены класса являются публичными?

Ответы [ 4 ]

5 голосов
/ 22 июня 2011

просто typeof(this).stringof

однако это исправлено во время компиляции, поэтому наследование не меняет значение

this.typeinfo.name

даст динамическое имя имени класса экземпляра

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

3 голосов
/ 22 июня 2011

Вы можете получить имя класса, просто используя ClassName.stringof.

Если вы хотите использовать его как виртуальную функцию, я бы рекомендовал использовать шаблон Curily RecurringPattern :

class B
{
    abstract string getName();
}

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

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

К сожалению, на данный момент нет способа определить, какие члены класса являются публичными.Вы можете перебрать всех членов, используя черту allMembers .

foreach (member; __traits(allMembers, MyClass))
    writeln(member);
3 голосов
/ 22 июня 2011

Это известно во время компиляции, но для оценки имени класса во время выполнения, я думаю, требуется разделение.

Вот оно, если оценка выполнения в порядке:

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);
}
0 голосов
/ 06 мая 2019

Вот то, что работает для меня - при условии, что оценка времени выполнения в порядке, и вас интересует только фактический класс имя без пути к пакету или имени модуля.

#!/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");
}

...