D mixin与工厂

mav*_*rik 2 factory d mixins

考虑我有以下课程:

/// 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"; };
}
Run Code Online (Sandbox Code Playgroud)

现在我想在其他地方实施工厂,例如:

/// 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());
}
Run Code Online (Sandbox Code Playgroud)

编译器(dmd 2.058)说:

factory.d(7): Error argument C1 to typeof is not an expression
Run Code Online (Sandbox Code Playgroud)

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

auto c = cast(C1) Object.factory("classes.C1");
Run Code Online (Sandbox Code Playgroud)

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

dav*_*v1d 5

mixin(`auto c = cast(typeof(C1)) Object.factory("C1");`)
Run Code Online (Sandbox Code Playgroud)

我不明白你的问题,我想:你想在运行时动态地转换为给定的类型?这在静态类型语言中是不可能的!你可以做的是,传递你的类(或其他)作为void*和使用开关...案例将其转换为所需的类型(你也可以使用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) {
}
Run Code Online (Sandbox Code Playgroud)

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

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

如果你只是想获得该类型的字符串typeof(bar).stringof将给你类型的bar字符串(但这在编译时已知).


Jon*_*vis 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");
Run Code Online (Sandbox Code Playgroud)

std.variant可以使用它来保存不同类型(它在内部使用联合).

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