再论枚举

实现枚举的方法

Rust的enum也可以用impl实现方法。

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

impl Message {
    fn call(&self) {
        match self {
            &Message::Quit => println!("Quit"),
            &Message::Move { x, y } => println!("Move: {},{}", x, y),
            &Message::ChangeColor(x, y, z) => println!("ChangeColor: {},{},{}", x, y, z),
            &Message::Write(ref s) => println!("Write {}",s)
        }
    }
}


fn main() {
    let msg = Message::Move{x:1,y:2};
    msg.call();    // 打印:Move: 1,2
}

上例中的Message的call方法也可以这样定义:

impl Message {
    fn call(&self) {
        match *self {
            Message::Quit => println!("Quit"),
            Message::Move { x, y } => println!("Move: {},{}", x, y),
            Message::ChangeColor(x, y, z) => println!("ChangeColor: {},{},{}", x, y, z),
            Message::Write(ref s) => println!("Write {}",s)
        }
    }
}

推荐使用第二种写法(官方文档是这样写的)。

就是不能写成这样:

        match self {
            Message::Quit => println!("Quit"),
            Message::Move { x, y } => println!("Move: {},{}", x, y),
            Message::ChangeColor(x, y, z) => println!("ChangeColor: {},{},{}", x, y, z),
        }
    }
}

self本身是一个引用类型,即&Message,所以放到match语句中需要与匹配的类型对应起来。

  • self 匹配 &Message
  • *self 匹配 Message

值得注意,match非常简单的就匹配了i32这种Copy类型的数据。对String这种非Copy类型在match中需要使用ref显式引用。

Rust的enum为何强大?

首先,我们要明白enum什么样的数据结构?

enum是一种类型类。其中包含了各种子类型。

其他语言,比如Java,每种子类型所拥有的字段及方法必须一样。这显然限制了枚举的概念。

例:

public enum Person {
    Male("man"),Female("woman");

    private String name;
    private Person(String name) {
        this.name = name;
    }

    public String getName() {
        if(this == Male){
            return "he is a " + this.name; 
        } else if(this == Female) {
            return "she is a " + this.name;
        } else {
            return "it is not human";
        }
    }
}

可以看到Java的枚举类的不同枚举类型即便是“相同方法不同行为”,实现起来都非常费力。

再看Rust,Rust的enum的元素可以是不同的复合类型,这比Java及其他语言强大多了。在enum的方法中使用模式匹配,在代码层面更加清晰简单。

例:

enum Person {
    Male,
    Female
}

impl Person {
    fn name(&self) -> String {
        match *self {
            Person::Male => String::from("he is a man"),
            Person::Female => String::from("she is a woman"),
            _ => String::from("it is not human")  // 这行可以不需要。
        }
    }
}


fn main() {
    let p = Person::Female;
    let s = p.name();
    println!("{}",s);    // 打印:she is a woman
}

results matching ""

    No results matching ""