跳转到内容

D 语言入门指南/模板和泛型编程/Mixins

来自 Wikibooks,开放的书籍,开放的世界

D 的类只支持单继承和接口。虽然接口足以重现多重继承的许多用途,但有些事情它们无法做到。Mixins 最初被添加到语言中是为了弥补这些不足。

普通模板

[编辑 | 编辑源代码]

在讨论 mixins 之前,有必要讨论模板的正常语法。前两章中讨论的类和函数模板语法实际上是正规语法的简写形式。“正常”模板看起来像这样

template Foo(A, B, C)
{
    A a;
    B b;
    C c;
}

模板由名称(Foo)、参数列表(A、B、C)和一系列声明(a、b、c)组成。当模板被实例化时,参数将被实例化提供的参数替换。声明被放置在与模板相同的范围内。

alias Foo!(int, real, char[]) F;
F.a = 10;
F.b = 5.8;
F.c = "hello!";

由于上面的例子不太有用,这里介绍了上一节中“min”函数的长格式。

template min(T)
{
    T min(T t1, T t2)
    {
        if (t1 < t2) return t1;
        else return t2;
    }
}

这也展示了 D 模板的另一个有趣特性。如果模板包含一个声明,并且该声明与模板同名,那么可以隐式地引用该成员。结合 _隐式函数模板实例化_(在上一节中讨论过),以下都是等效的

min!(int).min(1, 2); // long form
min!(int)(1, 2); // with the single-element rule
min(1, 2); // with IFTI

通常,当模板被实例化时,它的声明会被插入到模板所在的任何范围内。在 mixin 中,声明可以被插入到当前范围内。一个简单的例子如下所示

template Foo()
{
    int i;
    char[] s;
}
struct S
{
    mixin Foo;
}

(注意,如果模板的参数列表为空,那么 mixin 可以省略!())。结果是结构 S 有两个成员int ichar[] s.

Mixins 也可以命名,允许相同的 mixin 多次混合到当前范围内。这是一个更复杂的例子。

template Writer(T)
{
    void write(T t)
    {
        writefln(t);
    }
}
struct S
{
    mixin Writer!(int) IntWriter;
    mixin Writer!(char[]) StrWriter;
}
S s;
s.IntWriter.write(12);
s.StrWriter.write("hello!");
华夏公益教科书