仓颉语言泛型接口深度解析:从标准库 Iterable 到自定义可遍历容器

发布时间:2026/10/15 20:16:51
仓颉语言泛型接口深度解析:从标准库 Iterable 到自定义可遍历容器 文档编程语言【免费下载链接】cangjie_docs仓颉编程语言开发者文档。项目地址https://gitcode.com/Cangjie/cangjie_docs点击查看免费下载泛型接口是仓颉语言抽象与复用的核心机制之一它允许在声明接口时暂不固定成员涉及的具体类型而由使用者在使用时指定。本篇以标准库Iterable/Iterator/Collection为切入点系统讲解泛型接口的定义、继承、约束与型变规则并结合本仓库 泛型系列文档 与 集合遍历文档给出可直接落地到自定义容器的实战方案。读完本篇你将能独立定义带类型形参的接口、让自定义类型接入for-in遍历并理解泛型约束与子类型关系的底层规则。为什么接口需要泛型类型形参的引入仓颉语言中的泛型即参数化类型——一个在声明时未知、需要在使用时指定的类型。在 泛型概述 中定义了四个贯穿整个泛型体系的核心术语类型形参类型或函数声明中需要在使用处被指定的类型声明时给定标识符以便在声明体中引用类型变元在声明体中通过标识符引用这些类型形参时的称呼类型实参使用泛型声明时实际传入的具体类型类型构造器需要零个、一个或多个类型作为实参的类型。例如ListT中的T是类型形参elem: OptionT中对T的引用是类型变元ListInt64中的Int64是类型实参而List本身是类型构造器。仓颉中function、class、interface、struct与enum的声明都可以带类型形参。接口作为只描述行为、不包含数据的抽象类型见 接口文档当其成员函数的行为与某个未知类型相关时就必须引入泛型参数。标准库示例Iterable、Iterator 与 Collection以标准库中定义的Iterable为例它的成员函数iterator需要返回一个Iterator类型该类型是容器的遍历器。Iterator内部有从容器类型中取出下一个元素的next成员函数而next的返回类型需要在使用时指定因此Iterator必须声明泛型参数。核心定义如下public interface IterableE { func iterator(): IteratorE } public interface IteratorE : IterableE { func next(): OptionE } public interface CollectionT : IterableT { prop size: Int64 func isEmpty(): Bool }逐行解读这段示例IterableE声明类型形参E元素的类型。iterator()返回IteratorE即遍历E类型元素的遍历器。凡是实现了IterableE的类型都可通过iterator()获得一个可逐元素取值的遍历器。IteratorE : IterableEIterator继承Iterable因此遍历器本身也可被遍历这是仓颉中接口继承接口的典型写法:表示子类型关系。next(): OptionE每次调用返回OptionE有元素时返回Some(e)遍历完毕返回None。CollectionT : IterableTCollection在IterableT基础上新增成员——属性size: Int64容器大小与成员函数isEmpty(): Bool是否为空。这说明泛型接口在继承时可以新增成员形成更具体的抽象层次。需要说明的是本示例出自 泛型接口文档用于讲解接口也可以是泛型的。而 Iterable 和 Collections 文档 展示了标准库实际形态的差异真实标准库中的IteratorT是以内置抽象类abstract class形式提供的同样通过:声明与IterableT的继承关系并提供next(): OptionT。无论接口还是抽象类形式其核心都一致——通过类型形参T将元素类型参数化。泛型接口的继承与实现接口继承一个接口可以继承多个接口接口可以继承一个或多个接口但不能继承类且继承时允许添加新的接口成员。泛型接口同样遵循这一规则例如上面的CollectionT : IterableT。若需同时继承多个用连接interface Calculable : Addable Subtractable { func mul(other: Int64): Int64 func div(other: Int64): Int64 }实现Calculable的类型必须同时补齐加减乘除全部成员。同理实现CollectionT的类型必须同时实现iterator()、next()若Iterator要求以及size属性与isEmpty()。实现途径与要求根据 接口文档仓颉中除 Tuple、VArray 和函数外的其他类型都可以实现接口共有三种途径在定义类型时直接声明实现class Foo : I通过扩展实现接口详见 扩展由语言内置实现。实现接口时需满足成员函数与操作符重载函数的名称、参数列表、返回类型与接口声明一致成员属性要求mut修饰一致且类型相同接口成员默认具有public语义实现类型也必须用public实现。唯一的例外是若接口成员返回类型为 class 类型实现函数允许返回其子类型。泛型接口作为泛型约束where 子句与带实参的接口泛型接口最常见的用途之一是作为其他泛型声明的约束。在 泛型约束文档 中约束通过where关键字声明where T1 : Interface1 Interface2表示T1必须同时实现Interface1与Interface2逗号,用于分隔不同形参的约束。只有声明了约束才能在泛型函数或泛型类型中调用对应接口的成员。泛型接口作为约束时必须带上类型实参。例如 泛型类文档 中的Map键值对节点open class NodeK, V where K : Hashable EquatableK { var key: OptionK OptionK.None var value: OptionV OptionV.None // ... }这里Equatable是泛型接口作为约束使用时写作EquatableK——即K必须实现与自身比较的相等性判定。K : Hashable EquatableK意为K需同时实现Hashable与EquatableK两个接口。再看一个泛型函数中使用接口约束的完整示例来自 泛型约束文档func genericPrintT(a: T) where T : ToString { println(a) } main() { genericPrintInt64(10) }输出10若传入未实现ToString的类型如一个函数类型(Int64) - Int64编译器会抛出泛型类型参数不满足约束的错误。泛型接口的型变规则用户自定义泛型不型变泛型接口实例化后同样存在子类型关系但仓颉对其有严格限制。泛型类型的子类型关系文档 给出了型变的精确定义对类型构造器T与类型参数X不型变T(A) : T(B)当且仅当A B协变T(A) : T(B)当且仅当A : B逆变T(A) : T(B)当且仅当B : A。仓颉规定所有用户自定义的泛型类型含泛型接口在其所有类型变元处都是不型变的。因此给定interface IX即便D : C成立ID : IC也不成立——只有A B时才有IA : IB。例外是内建类型内建元组类型对其元素类型协变内建函数类型在入参处逆变、返回处协变。这一限制牺牲了部分表达能力但规避了协变数组运行时抛异常一类安全问题。泛型接口的成员泛型成员函数与静态泛型函数接口的成员可以是实例的或静态的也可以本身是泛型的。泛型函数文档 展示了 interface 中定义泛型成员函数与静态泛型函数的写法import std.collection.ArrayList interface M { func fooT(a: T): T static func toStringT(b: ArrayListT): String where T : ToString } class C : M { public func fooS(a: S): S { // 实现 M::foo泛型参数名可以不同 a } public static func toStringT(b: ArrayListT) where T : ToString { var res for (s in b) { res s.toString() } res } }要点有二其一接口中的泛型成员函数与非泛型函数一样具有open语义实现时泛型形参名称不必与接口声明一致其二接口的静态成员函数或属性可以有默认实现也可没有——当约束泛型变元T为某接口子类型并在泛型函数中以T.typename()方式访问静态成员时需要保证T的实例化类型中所有静态成员都有实现见 接口文档 中的printTypeName示例。实战实现泛型接口让自定义容器支持 for-in 遍历泛型接口最有价值的实战场景就是让自定义类型接入语言内置的遍历语法。根据 Iterable 和 Collections 文档Range、Array、ArrayList 等都是通过实现Iterable来支持for-in的开发者自定义类型也可以做到。以下这段for-in代码let list [1, 2, 3] for (i in list) { println(i) }在底层等价于基于iterator()与next()的 while 循环let list [1, 2, 3] var it list.iterator() while (true) { match (it.next()) { case Some(i) println(i) case None break } }也可以写成在 while 条件中使用模式匹配的等价形式let list [1, 2, 3] var it list.iterator() while (let Some(i) - it.next()) { println(i) }基于此我们可以定义一个泛型的自定义列表MyListT实现IterableT接口并配套一个实现遍历逻辑的MyListIteratorT按本文讲解的接口视角编写标准库中Iterator以抽象类形态提供继承写法一致均需提供next实现import std.collection.ArrayList class MyListT : IterableT { var items: ArrayListT ArrayListT() public func add(item: T) { items.add(item) } public func iterator(): IteratorT { MyListIteratorT(this) } } class MyListIteratorT : IteratorT { let list: MyListT var index: Int64 0 init(list: MyListT) { this.list list } public func next(): OptionT { if (index list.items.size) { let item list.items[index] index 1 return Some(item) } else { return None } } } main() { let ml MyListInt64() ml.add(1) ml.add(2) ml.add(3) for (i in ml) { println(i) } }运行后将依次打印1、2、3。这里的机制与标准库容器完全一致for-in通过iterator()拿到遍历器反复调用next()直到返回None。同时IteratorT : IterableT这一继承关系保证了遍历器本身也可以被for-in或嵌套遍历继续消费。若容器需要被当作CollectionT使用还需补上size属性与isEmpty()成员。小结泛型接口把抽象行为与待定类型结合在一起是仓颉泛型体系与面向接口编程的交叉点。通过 泛型接口文档 的Iterable/Iterator/Collection示例我们掌握了其定义与继承写法结合本仓库 泛型约束、泛型子类型关系、接口 与 Iterable 和 Collections 等文档进一步理解了接口约束、不型变规则、泛型成员函数以及for-in的底层展开逻辑。建议继续阅读 泛型类、泛型函数、泛型结构体 与 泛型枚举以获得对仓颉泛型机制的完整认识。赞分享文档编程语言【免费下载链接】cangjie_docs仓颉编程语言开发者文档。项目地址https://gitcode.com/Cangjie/cangjie_docs点击查看免费下载相关推荐仓颉语言集合遍历基石Iterable 接口与 for-in 语法深度解析仓颉语言集合遍历基石Iterable 接口与 for in 语法深度解析 Iterable 与 Iterator 是仓颉标准库中支撑所有集合遍历能力的一对核心文档编程语言仓颉语言 Iterable 与 Iteratorfor-in 遍历机制与自定义集合实现指南仓颉语言 Iterable 与 Iteratorfor in 遍历机制与自定义集合实现指南 导读 本文围绕仓颉Cangjie编程语言标准库中的 Itera文档编程语言仓颉语言泛型接口详解以 Iterable 与 Iterator 为例掌握参数化抽象的接口设计仓颉语言泛型接口详解以 Iterable 与 Iterator 为例掌握参数化抽象的接口设计 在仓颉编程语言Cangjie中泛型接口是连接“抽象行为契约文档编程语言创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询