D 语言入门指南/模板和泛型编程/Mixins
外观
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 i和char[] 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!");