代码写明 Rust 中的泛型型变
Variance
译作型变
或可变性
或变体
.
表示"泛型类型的子类型关系"如何从"泛型参数的子类型关系"中推导.
定义
无法理解时, 不要深究, 看完后再读一遍此定义即可.
假设1
C<T>
是一个泛型类或接口,T
是类型参数.假设2 类型
Dog
是Animal
的子类型.定义1
Covariance/Covariant
译作协变
:
如果C<Dog>
是C<Animal>
的子类型, 那么C<T>
对T
协变.定义2
Contravariance/Contravariant
译作逆变
:
如果C<Animal>
是C<Dog>
的子类型, 那么C<T>
对T
逆变.定义3
Invariance/Invariant
译作不变
, 或译作抗变
:C<T>
对T
既不是协变也不是逆变, 那么C<T>
对T
不变.
子类型的证明
let mut t1: T1 = make_t1();
let t2: T2 = make_t2();
// 在排除 type coerced 类型强制转换后, 以下证明有效
// 1. 赋值证明
let _t1: T1 = t2; // 证明`T2` 是 `T1` 的子类型
t1 = t2; // 可赋值, 证明`T2` 是 `T1` 的子类型
// 2. 函数调用证明
fn use_t1(v: T1) {}
use_t1(t2); // 实参类型 `T2` 可以替代形参类型 `T1`, 证明 `T2` 是 `T1` 的子类型
函数调用证明的适用范围更广:
许多类型写不出, 比如闭包
自动推导的生存期写不出
许多泛型参数是调用处才能确定类型
必须排除 type coerced 类型强制转换:
let string1: String = String::from("abc");
let str1: &str = &string1; // 不能证明 `&String` 是 `&str` 的子类型
生存期子类型
Rust 没有实际类型 struct
, enum
和 union
的继承,
子类型关系只体现在生存期上, 可以通过赋值来证明.
子类型的值可以转型为父类型:
fn lifetime_subtype<'long: 'short, 'short, T: Copy>(a: &'short T, b: &'long T) {
let _long_to_short: &'short T = b; // 成功 子类型的值可以转型为父类型
}
泛型参数'long: 'short
定义'long
是'short
的子类型,
意味着'long
是一个较长的生存期, 它能完全覆盖'short
这个较短的生存期,
那么任何一个需要&'short i32
的地方(转型,赋值,参数)&'long i32
都可以满足的,
所以&'long i32
是&'short i32
的子类型.
父类型的值不可以转型为子类型:
fn lifetime_subtype<'long: 's