| name | cangjie-generic |
| description | 仓颉语言泛型。当需要了解仓颉语言的泛型函数、泛型类、泛型接口、泛型结构体、泛型枚举、泛型约束(where)、泛型子类型关系、型变(不变/协变/逆变)、类型别名(type)等特性时,应使用此 Skill。 |
仓颉语言泛型 Skill
1. 泛型概述
1.1 核心概念
- 泛型 = 参数化类型 — 声明时未知类型,使用时指定
- 支持泛型的结构:
function、class、interface、struct、enum
1.2 术语
| 术语 | 含义 |
|---|
| 类型形参 | 须在使用处指定的类型。使用标识符在体内引用 |
| 类型变元 | 在体内引用类型形参的标识符 |
| 类型实参 | 使用泛型声明时提供的具体类型 |
| 类型构造器 | 接受零个或多个类型作为参数以产生具体类型的类型 |
1.3 语法
- 类型参数在类型/函数名后使用尖括号
<...> 声明
- 示例:
class List<T> — T 是类型参数;List<Int64> — Int64 是类型实参;List 是类型构造器
2. 泛型函数
2.1 声明
2.2 分类
(a) 全局泛型函数
func id<T>(a: T): T { return a }
(b) 局部泛型函数
(c) 泛型成员函数
class、struct、enum 可有泛型成员函数
- 约束用
where 指定:
class A {
func foo<T>(a: T): Unit where T <: ToString { println("${a}") }
}
(d) 扩展中的泛型函数
(e) 静态泛型函数
interface、class、struct、enum、extend 可定义静态泛型函数
3. 泛型类
3.1 声明
open class Node<K, V> where K <: Hashable & Equatable<K> {
var key: Option<K> = Option<K>.None
var value: Option<V> = Option<V>.None
}
3.2 静态成员限制
- 泛型类的静态成员变量/属性在所有实例化之间共享内存
- 因此静态成员变量/属性的类型声明和表达式不能引用类型参数或包含未实例化的泛型类型表达式
- 静态变量/属性初始化表达式不能调用泛型类自身的静态成员函数或属性
4. 泛型接口
4.1 声明
public interface Iterable<E> {
func iterator(): Iterator<E>
}
5. 泛型结构体
5.1 声明
struct Pair<T, U> {
let x: T
let y: U
public init(a: T, b: U) { x = a; y = b }
}
6. 泛型枚举
6.1 声明
- 枚举构造函数可携带泛型类型的载荷
- 典型例子是
Option<T>:
public enum Option<T> {
Some(T)
| None
}
7. 泛型约束
7.1 目的
- 约束指定类型参数须具备的操作/能力
- 无约束时只能传递/返回泛型类型的值,不能进行其他操作
7.2 语法
- 使用
where 关键字,放在声明体之前
- 格式:
where T1 <: Interface, T2 <: Class
- 同一变量的多个约束用
&:where T1 <: Interface1 & Interface2
7.3 接口约束
func genericPrint<T>(a: T) where T <: ToString {
println(a)
}
7.4 类约束
class Zoo<T> where T <: Animal { ... }
7.5 规则
- 约束只能是具体类类型或接口
- 若类型变量有多个类的上界,它们须在同一继承链上
8. 泛型子类型关系
8.1 实例化子类型关系
- 若
class C<Z> <: I<Z, Z>,则 C<Bool> <: I<Bool, Bool>、C<D> <: I<D, D> 等
8.2 型变 — 用户自定义类型不变
| 型变 | 条件 |
|---|
| 不变 | T(A) <: T(B) ⟺ A = B |
| 协变 | T(A) <: T(B) ⟺ A <: B |
| 逆变 | T(A) <: T(B) ⟺ B <: A |
8.3 内置例外
- 元组类型在每个元素类型上协变
- 函数类型在参数类型上逆变,在返回类型上协变
9. 类型别名
9.1 声明
- 关键字:
type
- 语法:
type Alias = OriginalType
- 不创建新类型 — 仅为替代名称
9.2 规则
- 仅限顶层 — 不能在函数内定义
- 原始类型须在别名定义处可见
- 不允许循环引用 — 直接或间接循环均禁止
9.3 使用场景
- 作为类型:
var a: A = B() 其中 type A = B
- 作为构造函数(当别名指向 class/struct 时):
A() 构造 B
- 访问静态成员:
A.foo()、A.b
- 访问枚举构造函数:
Time.Day 其中 type Time = TimeUnit
9.4 限制
9.5 泛型类型别名
- 类型别名可声明类型参数
- 不能对别名类型参数使用
where 约束
type RD<T> = RecordData<T>
10. 完整特性矩阵
| 特性 | function | class | interface | struct | enum |
|---|
| 类型参数 | ✅ | ✅ | ✅ | ✅ | ✅ |
where 约束 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 泛型成员函数 | — | ✅ | ✅ | ✅ | ✅ |
| 静态泛型函数 | — | ✅ | ✅ | ✅ | ✅ |
| 扩展中的泛型 | ✅ | — | — | — | — |
| 类型别名 | — | ✅ | — | ✅ | ✅ |
| 子类型型变 | — | 不变 | 不变 | 不变 | 不变 |