类型系统

Rust类型系统特点

类型系统分类图

类型系统分类图

三个标准

  1. 隐式转换
  2. 检查时机
  3. 多态支持

Rust的类型系统有什么特点?

Rust的类型系统有什么特点?

强类型 + 静态类型 + 显式类型

类型分类

原生类型

Rust原生类型

Rust原生类型

组合类型

Rust组合类型

Rust组合类型

自定义组合类型

小例子

常量

常量定义使用

const PI: f64 = std::f64::consts::PI;
static E: f32 = std::f32::consts::E;

fn main() {
    const V: u32 = 10;
    static V1: &str = "hello";
    println!("PI: {}, E: {}, V {}, V1: {}", PI, E, V, V1);
}

类型推导

Rust编译器可以从上下文自动推导类型

use std::collections::BTreeMap;

fn main() {
    let mut map = BTreeMap::new();
    // 没有这一行就缺少自动推导信息
    // map.insert("hello", "world");
    println!("map: {:?}", map);
}

把第 5 行这个作用域内的 insert 语句注释去掉,Rust 编译器就会报错:“cannot infer type for type parameter K”。

Rust编译器不能获取足够上下文信息时,就需要明确类型

  1. 无法自动推导collect返回什么类型

fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    let even_numbers = numbers
        .into_iter()
        .filter(|n| n % 2 == 0)
        .collect();

    println!("{:?}", even_numbers);
}

  1. 给even_numbers添加类型声明即可

fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    let even_numbers: Vec<_> = numbers
        .into_iter()
        .filter(|n| n % 2 == 0)
        .collect();

    println!("{:?}", even_numbers);
}

这里编译器只是无法推断出集合类型,但集合类型内部元素的类型,还是可以根据上下文得出,所以我们可以简写成 Vec<_>

  1. 也可以让 collect 返回一个明确的类型

fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    let even_numbers = numbers
        .into_iter()
        .filter(|n| n % 2 == 0)
        .collect::<Vec<_>>();

    println!("{:?}", even_numbers);
}

这里在泛型函数后使用 :: 来强制使用类型 T,这种写法被称为 turbofish

Turbofish

一个对 IP 地址和端口转换的例子


use std::net::SocketAddr;

fn main() {
    let addr = "127.0.0.1:8080".parse::<SocketAddr>().unwrap();
    println!("addr: {:?}, port: {:?}", addr.ip(), addr.port());
}

如果类型在上下文无法被推导出来,又没有 turbofish 的写法,我们就不得不先给一个局部变量赋值时声明类型,然后再返回,这样代码就变得冗余

#![allow(unused)]
fn main() {
match data {
    Some(s) => v.parse::<User>()?,
    _ => return Err(...),
}
}