封装

现在我们对模块和可见性有了基本的了解,让我们回到封装的概念上来。封装是隐藏对象内部表示的做法,最常用于强制执行对象状态的一些不变量

回到我们的Ticket结构体:

#![allow(unused)]
fn main() {
struct Ticket {
    title: String,
    description: String,
    status: String,
}
}

如果所有字段都是公开的,就没有封装。你必须假设字段可以在任何时候被修改为由其类型允许的任何值。你不能排除票证明确实可能有空标题或没有意义的状态。

为了执行更严格的规则,我们必须保持字段私有1。然后,我们可以提供公共方法来与Ticket实例交互。那些公共方法将负责维护我们的不变量(例如,标题不能为空)。

如果所有字段都是私有的,那么就不能直接使用结构体实例化语法创建Ticket实例了:

#![allow(unused)]
fn main() {
// 这样做不行!
let ticket = Ticket {
    title: "建立一个工单系统".into(),
    description: "创建一个可以在看板上管理工单的系统".into(),
    status: "打开".into()}
}

在前面关于可见性的练习中你已经看到了这个操作。我们现在需要提供一个或多个构造函数,即可以从模块外部使用的静态方法或函数来创建结构体的新实例。幸运的是,我们已经有了一个:Ticket::new,如之前练习中实现的这里

访问器方法

总结一下:

  • Ticket的所有字段都是私有的
  • 我们提供了一个构造函数,Ticket::new,它在创建时强制执行了我们的验证规则

这是一个好的开始,但还不够:除了创建Ticket之外,我们还需要与其交互。但如果字段是私有的,我们怎么访问呢?

我们需要提供访问器方法。访问器方法是公共方法,允许你读取私有结构体字段(或字段)的值。

Rust不像其他一些语言那样内置了为你生成访问器方法的方式。你需要自己编写它们——它们只是常规的方法。

参考

  • 本节练习位于 exercises/03_ticket_v1/05_encapsulation
1

或者细化它们的类型,这是我们将在后面探索的技术这里