泛型(Generics)
泛型把「类型的形状」与「具体类型」解耦:类型与函数都带类型参数,调用时才定下实例化。约束用 where 子句表达,约束面即能力面。
泛型类型
struct Box<T>
{
public var value: T;
public func Get() -> T => value;
public func Replaced(nv: T) -> Box<T> => new Box<T>() { value: nv };
}
val bi = new Box<int>();
bi.value = 42;
print(bi.Get(), bi.Replaced(7).Get());
val bs = new Box<string>();
bs.value = "字";
print(bs.Get());42 7
字Box<int> 与 Box<string> 是不同的实例化,各自有自己的成员面。嵌套实例化合法:Box<list<int>> 里装列表。
泛型函数
func First<T>(xs: list<T>) -> T?
{
if xs.Count == 0
{
return null;
}
return xs[0];
}
val empty = new list<string>();
print(First(empty) == null);
val names = new list<string>();
names.Add("甲");
print(First(names));True
甲where 约束与运算符放行
约束写在返回类型之前(子句顺序 uses → fail → where → ->),约束声明「T 必须具备的能力」,泛型体内按约束放行运算:
import Math.*;
func Sum2<T>(a: T, b: T) where T: Numeric -> T
{
return a + b;
}
print(Sum2(2, 3), Sum2(1.5, 2.5));5 4Numeric 是 std Math 的协议(四则 + 判等),内建标量隐式满足,a + b 按约束协议的运算符签名放行。约束可以写多条:where T: Ordered, Clone 单子句多约束,或多个 where 子句。
构造签名约束
约束协议声明 init() 时,泛型体内获得 new T() 的能力,实例化时按具体类型的构造器构造:
import Collections.*;
protocol Makeable
{
init();
}
struct Token
{
public var stamp: string = "生成";
}
func Make<T>() where T: Makeable -> T
{
return new T();
}
val t = Make<Token>();
print(t.stamp);生成没有 init 约束时 new T() 会直接编译期报错,因为无法确定对面的 T 是否允许被无参构造。
一元运算符约束
约束协议也能声明一元运算符。operator -(self) -> Self; 让泛型体里的 -x 放行:
protocol Neg
{
operator -(self) -> Self;
}
func Negate<T>(x: T) where T: Neg -> T
{
return -x;
}
print(Negate(5));-5实参侧按内建运算能力判定满足:uint / byte 没有一元负。
注意
- 约束写在返回类型之前(uses → fail → where →
->),不能写到->的右侧。 - 约束可多约束并存:
where T: Ordered, Clone单子句多约束,或多个 where 子句各管一个类型参数。 - 约束面没有的运算符用了报 MS3144,错误信息会指出该补充的协议。
list<T>/map<K, V>都是泛型容器的现成范例,方法面见容器与文本。
最后更新于 2026年10月9日
