Rust中标记类型


Rust中,"marker types"(标记类型)是一种特殊的类型,它们通常没有具体的数据,而是用于在编译时传达一些关于类型的信息,或者为了满足特定的 trait 约定。

这些类型通常被称为“标记类型”,因为它们在程序中充当一种标记,而不是用于携带数据的实际容器。它们的存在主要是为了在编译时进行类型检查和在运行时进行一些特殊的行为。


枚举类型
枚举类型允许你定义一组可能的值,每个值都可以包含不同的数据。这样的枚举类型常常被用于标记或表示某个实体的不同状态。
例如,考虑一个简单的文档类型,可以是草稿状态或已发布状态。这可以通过枚举来实现,其中每个状态都有不同的关联数据:

你可以使用枚举类型来表示处于“Draft”或“Published”文档的两个状态,下面是一个简单的示例:

// 定义一个枚举类型来表示文档的状态
enum DocumentStatus {
    Draft,
    Published,
}

// 定义文档结构,使用结构来包装实际的文档数据和状态
struct Document {
    content: String,
    status: DocumentStatus,
}

// 实现文档的相关方法
impl Document {
   
// 创建一个新的草稿文档
    fn new_draft(content: &str) -> Document {
        Document {
            content: String::from(content),
            status: DocumentStatus::Draft,
        }
    }

   
// 发布文档,修改状态为已发布
    fn publish(&mut self) {
        self.status = DocumentStatus::Published;
    }

   
// 获取文档的内容和状态
    fn get_info(&self) {
        println!(
"Content: {}", self.content);
        match self.status {
            DocumentStatus::Draft => println!(
"Status: Draft"),
            DocumentStatus::Published => println!(
"Status: Published"),
        }
    }
}

fn main() {
   
// 创建一个新的草稿文档
    let mut draft_document = Document::new_draft(
"This is a draft document.");

   
// 打印文档信息(草稿状态)
    draft_document.get_info();

   
// 发布文档
    draft_document.publish();

   
// 打印文档信息(已发布状态)
    draft_document.get_info();
}


上例中使用枚举表达状态,这是常见简单的状态字段实现,比用整数1 2 3 代表状态要进一步。
这在其他语言中也可以实现。

结构类型
Rust类型系统中的有更强大“标记类型marker types”,可以是只有一个名称的结构struct。

下面是将“Draft”或“Published”建模状态模式对象的代码

// 定义草稿状态结构体
struct Draft;

// 定义已发布状态结构体
struct Published;

// 定义文档结构,使用泛型参数来表示状态
struct Document<T> {
    content: String,
    _state: T,
}

// 实现文档的相关方法
impl Document<Draft> {
   
// 创建一个新的草稿文档
    fn new_draft(content: &str) -> Document<Draft> {
        Document {
            content: String::from(content),
            _state: Draft,
        }
    }
}

impl Document<Published> {
   
// 发布文档,修改状态为已发布
    fn publish(self) -> Document<Published> {
        Document {
            content: self.content,
            _state: Published,
        }
    }
}

// 获取文档的信息的通用实现
impl<T> Document<T> {
    fn get_info(&self) {
        println!(
"Content: {}", self.content);
       
// 在这里你可以根据具体状态类型 T 执行不同的操作
    }
}

fn main() {
   
// 创建一个新的草稿文档
    let draft_document = Document::new_draft(
"This is a draft document.");

   
// 打印文档信息(草稿状态)
    draft_document.get_info();

   
// 发布文档
    let published_document = draft_document.publish();

   
// 打印文档信息(已发布状态)
    published_document.get_info();
}

将状态设计为类型对象,通过编程语言的类型系统约束检查误用状态,特别是全局变量性质的状态,这种权力受到类型制约才不容易出错。