2013-11-20 18 views
1

我可以在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]; 
} 

回答

3

是的,这是可能的,但不一定完全如何你有它。你可以创建一个类型为元组的类型列表:

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)