[Rust笔记] 代码写明 Rust 中的泛型型变

本文深入探讨Rust中的泛型型变,包括定义、子类型的证明、生存期子类型、协变、逆变和不变的概念,并通过实例详细解释了Rust泛型类型的型变推导过程。
摘要由CSDN通过智能技术生成

代码写明 Rust 中的泛型型变

Variance译作型变可变性变体.
表示"泛型类型的子类型关系"如何从"泛型参数的子类型关系"中推导.

定义

无法理解时, 不要深究, 看完后再读一遍此定义即可.

  • 假设1 C<T>是一个泛型类或接口, T是类型参数.

  • 假设2 类型DogAnimal的子类型.

  • 定义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 没有实际类型 structenum 和 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值