我可以在D中创建类数组吗?就像:D类中的类Array
interface A {}
class AA: A {}
class AB: A {}
class AC: A {}
ClassList!A list = new ClassList!A {AA, AB, AC};
void testf(ulong testv) {
A a = new list[testv];
}
我可以在D中创建类数组吗?就像:D类中的类Array
interface A {}
class AA: A {}
class AB: A {}
class AC: A {}
ClassList!A list = new ClassList!A {AA, AB, AC};
void testf(ulong testv) {
A a = new list[testv];
}
是的,这是可能的,但不一定完全如何你有它。你可以创建一个类型为元组的类型列表:
import std.typetuple;
alias list = TypeTuple!(AA, AB, AC);
但是,你不能在运行时将它索引为一个数组;尝试new list[n]
将是编译时错误。相反,你会创建一个上循环,并返回该实例,像这样的辅助函数:
foreach(index, type; list)
if(index == testv) {
a = new type();
break;
}
,编译是foreach(foo; compile_time_list)
实际上变成一个大的展开循环的方式。生成的代码,如果你写道:
if(0 == testv) { a = new AA(); goto end; }
if(1 == testv) { a = new AB(); goto end; }
if(2 == testv) { a = new AC(); goto end; }
end:
因此与运行时的值工作,消除编译时间列表,你想数组索引之间的差距。
值得注意的是,这不一定是最有效的,但除非你的班级名单有一千个条目,我怀疑这一点很重要。另一个提高速度的方法是在编译时从列表中生成一个switch语句,然后将其混合。switch语句将编译为更高效的查找表。但赔率是简单的循环是好的。
无论如何,把它在一起,我们得到:
import std.stdio;
interface A {}
class AA: A {}
class AB: A {}
class AC: A {}
import std.typetuple;
alias list = TypeTuple!(AA, AB, AC);
void testf(ulong testv) {
A a;
foreach(index, type; list)
if(index == testv) {
a = new type();
break;
}
if(a is null)
writeln("bad type index");
else {
writeln(typeid(cast(Object) a), " was created");
}
}
void main() {
testf(0);
testf(1);
testf(2);
testf(3);
}
结果:
$ ./test50
test50.AA was created
test50.AB was created
test50.AC was created
bad type index
正是我们想要的。
顺便说一句,typeid(cast(Object) a)
可能看起来很奇怪,那就是获取类型的动态类。它必须首先投射到Object,因为否则它会打印界面名称。由于D接口不一定是D类(它们也可以是COM对象或C++类),所以typeid并不总是可用的。强制转换为对象可确保它是D类,从而获取运行时类型的详细信息。
编辑:我看到你问新闻组以及检查循环中的基类。下面是如何做到这一点:
你可以为它编写自己的元组模板,或者让 编译在工厂函数上失败:A a = new T();将 失败,如果A是不是T.
基类或接口把检查列表看起来是这样的:
bool checkClassList(Base, T...)() {
foreach(t; T) {
static if(!is(t : Base))
static assert(0, t.stringof ~ " is not a child of " ~ Base.stringof);
}
return true;
}
template ClassList(Base, T...) if(checkClassList!(Base, T)) {
alias ClassList = T;
}
用法:
alias list = ClassList!(A, AA, AB, AC); // good
地址:
class B {}
alias list = ClassList!(A, AA, AB, AC, B);
并获取错误:
test50.d(12): Error: static assert "B is not a child of A"
test50.d(19): instantiated from here: checkClassList!(A, AA, AB, AC, B)