15、Encapsulation(封装)

Encapsulation(封装)

封装

既然我们已经对模块和可见性有了基本的了解,那么让我们回到封装上来。

封装是隐藏对象内部表示的做法。它最常用于强制实施对象状态的一些不变性(invariants)。

让我们回顾Ticket结构体

struct Ticket {
    title: String,
    description: String,
    status: String,
}

如果所有字段都是公有的,那么这里就没有封装。

我们必须假设这些字段可以随时修改,并设置为其类型允许的任何值。也不能排除title为空或status没有意义等情况(也就是说要保留字段合法性检查)

为了实现我们上面提到过的规则,或是实现更加严格、复杂的规则,我们必须将字段设置为private,避免外部直接修改字段,而绕过自定义的合法性检查代码。为了确保能够修改,正常使用这个实例,我们要提供与Ticket实例交互的public方法,这些方法负责维护我们的对象状态的不变性(invariants)。

如果至少有一个字段是私有的,那么就无法再使用结构体实例化语法直接创建Ticket示例:

// This won't work!
// 这将不会工作!
let ticket = Ticket {
    title: "Build a ticket system".into(),
    description: "A Kanban board".into(),
    status: "Open".into()
};

上一个关于可见性的章节的课后习题,就体现了这一点,最后我是把所有字段都设置为了public才可以操作。

那么,现在我们就必须提供一个或多个公共的构造函数——就是可以从模块外部使用的静态方法或函数,可以调用以创建结构体的新实例。

幸运的是,我们已经有了一个这样的构造函数,就是Ticket::new,在Validation这一节(其实就是String那一节,因为RustRover给的知识点很少,我专门去别的地方学习的字符串类型)实现了。

访问器方法

综上所述:

  1. 所有Ticket的字段都是私有的
  2. 我们提供了一个公共的构造函数,Ticket::new,可以在创建Ticket实例时强制执行我们的验证规则

但是上面那些还不够,如果只能创建,并且字段是私有的,那么我们就无法访问并修改它。

所以,我们需要提供访问器方法

访问器方法是公共方法,它允许我们读取结构体中的某个或多个私有字段。

这,就是封装

其实这也算是一个面向对象语言的一个很常规的特性了,Java里面就特别强调封装,好像还称为Java Bean?还有各种各样的库方便我们使用封装,比如大名鼎鼎的lombok(我应该没说错吧…Java并不是学的特别好其实)

OMG,Rust并不像其他语言那样可以创建访问器方法的内置方式,我们必须手动编写它们,因为它们只是常规方法(

练习

这次的练习慢慢的结合之前的学习的内容了,不是那么过分的把读者当傻子那样的简单了(虽然也还是超级简单就对了…

我们要实现三个访问器方法,可以读取Ticket实例的三个私有字段

image-20250902214614078

以下是我的答案:

image-20250902214805105

也是顺利通过了欸

以上就是这一节的学习内容了

阅读剩余
THE END