33、枚举

枚举

上一个章节学Trait的时候,用的是Ticket这个结构体的例子,Ticket只有三个状态:To-DoInProgressDone

 

但是Ticket结构体里的status字段,或new方法里参数的类型,并不能很好的体现这一点。

#[derive(Debug, PartialEq)]
pub struct Ticket {
    title: String,
    description: String,
    status: String,
}

impl Ticket {
    pub fn new(
        title: String, 
        description: String, 
        status: String
    ) -> Self {
        // [...]
    }
}

 

这都是用String来表示status字段。String是一种非常通用的类型——它不能很好的传达status字段有一组有限的可能值的信息。更糟糕的是,Ticket::new的调用者,只有在运行时才能发现它们提供的类型是否有效。

 

所以我们可以使用枚举类型。

 

enum

枚举是一种可以具有一组固定值的类型,称为variants(变体)。

 

在Rust中,使用enum关键字来定义一个枚举类型:

enum Status {
    ToDo,
    InProgress,
    Done,
}

 

enum,就像struct一样,定义了一种新的Rust类型。

 

练习

 

完成/* TODO */的内容

 

// TODO: use `Status` as type for `Ticket::status`
//   Adjust the signature and implementation of all other methods as necessary.

#[derive(Debug, PartialEq)]
// `derive`s are recursive: it can only derive `PartialEq` if all fields also implement `PartialEq`.
// Same holds for `Debug`. Do what you must with `Status` to make this work.
pub struct Ticket {
    title: String,
    description: String,
    status: Status,
}

/* TODO */
pub enum Status {
    /* TODO */

impl Ticket {
    pub fn new(title: String, description: String, status: St/* TODO */-> Ticket {
        if title.is_empty() {
            panic!("Title cannot be empty");
        }
        if title.len() > 50 {
            panic!("Title cannot be longer than 50 bytes");
        }
        if description.is_empty() {
            panic!("Description cannot be empty");
        }
        if description.len() > 500 {
            panic!("Description cannot be longer than 500 bytes");
        }

        Ticket {
            title,
            description,
            status,
        }
    }

    pub fn title(&self) -> &String {
        &self.title
    }

    pub fn description(&self) -> &String {
        &self.description
    }

    pub fn status(&self) -> &/* TODO */{
        &self.status
    }
}

 

这个代码其实挺好弄的,照葫芦画瓢就可以了,不过我发现我最近的代码总是被奇怪的问题通过不了,这次的代码,别的地方写的都挺好的,就#[derive(Debug,PartialEq,Clone,Copy)]没写CopyClone,导致发生了所有权失效的问题。这个Copy和Clone一定要写吗?这一块的问题隐藏的很隐蔽?不知道,以后我长点记性好了(

 

// TODO: use `Status` as type for `Ticket::status`
//   Adjust the signature and implementation of all other methods as necessary.

#[derive(Debug, PartialEq)]
// `derive`s are recursive: it can only derive `PartialEq` if all fields also implement `PartialEq`.
// Same holds for `Debug`. Do what you must with `Status` to make this work.
pub struct Ticket {
    title: String,
    description: String,
    status: Status,
}

#[derive(Debug,PartialEq,Clone,Copy)]
pub enum Status {
    ToDo,
    InProgress,
    Done,
}

impl Ticket {
    pub fn new(title: String, description: String, status: Status)-> Ticket {
        if title.is_empty() {
            panic!("Title cannot be empty");
        }
        if title.len() > 50 {
            panic!("Title cannot be longer than 50 bytes");
        }
        if description.is_empty() {
            panic!("Description cannot be empty");
        }
        if description.len() > 500 {
            panic!("Description cannot be longer than 500 bytes");
        }

        Ticket {
            title,
            description,
            status,
        }
    }

    pub fn title(&self) -> &String {
        &self.title
    }

    pub fn description(&self) -> &String {
        &self.description
    }

    pub fn status(&self) -> &Status{
        &self.status
    }
}

 

这一节的学习就先到这里了(

阅读剩余
THE END