学习Rust 之 Enums and Pattern Matching

49 阅读2分钟

前言

我认为Enum在Rust里是一个极其重要的feature。它比大部分语言的Enum的强大多了。它不但可以表示一组常量,还可以表示一组类型。

Enum的特性

表示一组常量

enum IpAddrKind { V4, V6, }

这样定义了有以上2个值的枚举。

表示一组类型

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

注意其中每个类型里面的数据类型都可以是不一样的。

Enum的用途

虽然enum支持的特性,很简单就介绍完了。但是基于enum能做的事情很多。

Option

这是Option的定义

enum Option<T> {
    None,
    Some(T),
}

在Rust里,声明一种类型的时候,默认是非空的。把一种类型用Option包起来,可以表示可空的某个类型。 开发者在遇到可能为空的类型的值的时候,必须考虑它为空值的情形,否则无法通过编译,这样减少了错误。 而且,Rust标准库给Option提供了一大堆方法,帮助开发者处理可能为空的值。

match

match和enum组合起来,可以很方便地判断一个值的类型。对不同的类型的值,做不同的操作。

#[derive(Debug)] // so we can inspect the state in a minute
enum UsState {
    Alabama,
    Alaska,
}

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter(state) => {
            println!("State quarter from {:?}!", state);
            25
        }
    }
}

option常常和match结合起来使用。用来判断一个值为空还是非空,进行不同的操作。

fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}

相对于使用if else,match的好处是编译器会判断match的有没有覆盖所有可能的情况。当然,为了简单,可以给出一个用来兜底的分支。

如果只对某一个类型有兴趣,那就没必要使用match了,用 if let 代替即可。

总结

Enums 与 Pattern Matching结合可以很方便地对一个值进行类型的判断。相对于使用instanceof + if else,它们的好处是

  1. 语法更加简洁
  2. 判断类型更容易实现不重复也不漏掉。