考虑我有以下课程:
/// 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)。我想在运行时获取类型(如字符串)。
答案 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是静态类型的。