D mixin与工厂

时间:2012-07-19 18:02:37

标签: factory mixins d

考虑我有以下课程:

/// 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)。我想在运行时获取类型(如字符串)。

2 个答案:

答案 0 :(得分:5)

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

我不明白你的问题,我想: 您想在运行时动态转换为给定类型吗?这在静态类型语言中是不可能的!您可以做的是,将您的类(或其他)传递为void*并使用开关... 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) {
}

您还可以在编译时生成切换案例:

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

如果您只想获得typeof(bar).stringof类型的字符串,将为您提供bar类型的字符串(但这在编译时已知)。

答案 1 :(得分:5)

Mixins是一个编译时工件,只能在编译时使用。 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是静态类型的。