从一个对象中找出它是其实例的接口

Find out from an object as an interface whose instance it is

我有以下情况 (https://run.dlang.io/is/19OOW9):

import std.stdio;

void main(string[] args)
{
    inter1 c1 = new foo();
    foo c2 = new foo();
    writeln("Origin=interface: ", typeof(c1).stringof);
    writeln("Origin=class: ", typeof(c2).stringof);
}

interface inter1 {
}

class foo : inter1 {
}

我使用接口并为它们提供不同的实现。现在我需要知道当前正在使用哪个具体实现。所以在上面的例子中,我想从 c1 知道它是 class foo.

的一个实例

这在 D 语言中可能吗?

我已经尝试了object(例如TypeInfo_Class)和std.traits的可能性。可惜没有成功。

当然,解决方法是为接口提供合适的元方法 (https://run.dlang.io/is/Xnt0TO):

import std.stdio;

void main(string[] args)
{
    inter1 c1 = new foo();
    foo c2 = new foo();
    writeln("Origin=interface: ", c1.strategyName);
    writeln("Origin=class: ", c2.strategyName);
}

interface inter1 {
    @property string strategyName() const;
}

class foo : inter1 {
    @property string strategyName() const {
        return "foo";
    }
}

然而,这对于 D 来说是麻烦且不寻常的。我可以想象有更好的实现方式。

此致

托斯滕

实际上很简单:首先转换为 Object,然后获取 typeid,在 null 检查之后:

Object o = cast(Object) your_object;
if(o is null) { /* i don't think this ever happens but you should check anyway */ }
writeln(typeid(o)); // will tell the class name

如果你想调用特定 class 上的方法,你可以直接转换到你的 class,然后再次检查空值。

中间转换为 Object 允许 typeid(又名 classinfo)成功,而直接在接口上调用它总是 returns 接口本身的 typeid。这是因为 D 接口被定义为非常薄,以实现与其他语言的最大兼容性,并且不会自动假定 运行 时间类型信息实际上通过它存在。但是对 Object 的转换告诉它你假设 RTTI 存在,然后 typeid 将拉它。

请注意,typeid 数据不提供大量信息...它主要是动态转换、比较和语言 运行time 的其他功能所需要的。但是它有一个方便的方法是 class 名称和 toString 方法,这就是 writeln 成功的原因。但是,如果您正在寻找更详细的 运行 时间反射,则必须使用 CT 桥接功能来完成,或者可能更好,只需在界面中编写您自己的方法即可。

但如果您只需要 class 名称,请使用该 toString。它给出了完全限定的名称,包括模块名称,因此您将得到 yourmodule.foo 而不是 foo。如果你喜欢,你可以通过在点处切片来切断它。