2

考虑我有以下课程:

/// File classes.d
class C {
    string type() { return "C"; };
}

class C1 : C {
    override string type() { return "C1"; };
}

class C2 : C {
    override string type() { return "C1"; };
}

现在我想在其他地方实现一个工厂,比如:

/// File factory.d
module factory;
import std.functional;
import std.stdio;

void main() {
    mixin(import("classes.d"));
    auto c = cast(typeof(mixin("C1"))) Object.factory("C1");
    writeln(c.type());
}

编译器(dmd 2.058)告诉我:

factory.d(7): Error argument C1 to typeof is not an expression

我知道以下行编译得很好:

auto c = cast(C1) Object.factory("classes.C1");

但这需要我在编译时知道类型(C1)。我想在运行时获取类型(如字符串)。

4

2 回答 2

5
mixin(`auto c = cast(typeof(C1)) Object.factory("C1");`)

我不明白你的问题,我想:你想在运行时动态转换为给定的类型?这在静态类型语言中是不可能的!您可以做的是,传递您的类(或其他)void*并使用 switch ... case 将其转换为所需的类型(您也可以使用std.variant,这可能是更好的方法,但我从未使用过它)和然后调用不同的函数(模板函数):

final switch(which_type) {
    case "C1": foo(cast(C1)bar); break;
    case "C2": foo(cast(C2)bar); break;
}

void foo(T)(T a) {
}

您还可以在编译时生成 switch case:

final switch(which_type) {
    foreach(i; TypeTuple("C1", "C2")) {
        case i: foo(mixin(`cast(` ~ i ~ `)bar`); break;
    }
}

如果您只想获取类型的字符串,typeof(bar).stringof则会为您提供baras 字符串的类型(但这在编译时已经知道)。

于 2012-07-19T18:14:24.067 回答
5

Mixin 是编译时的工件,只能在编译时使用。typeof只能在编译时使用。D 是一种静态类型语言,所有类型必须在编译时已知。

你可以有一个引用派生类实例的基类类型的引用,所以这样的事情是可能的:

C makeC(string type)
{
    switch(type)
    {
        case "C": return new C;
        case "C1": return new C1;
        case "C2": return new C2;
        default: throw new Exception(format("%s is not a C", tye));
    }
}

C c = makeC("C1");

还有std.variant哪些可以用来保存不同的类型(它在内部使用联合)。

但是您无法决定变量在运行时的类型,因为 D 是静态类型的。

于 2012-07-19T18:24:25.700 回答