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给的知识点很少,我专门去别的地方学习的字符串类型)实现了。
访问器方法
综上所述:
- 所有
Ticket
的字段都是私有的 - 我们提供了一个公共的构造函数,
Ticket::new
,可以在创建Ticket
实例时强制执行我们的验证规则
但是上面那些还不够,如果只能创建,并且字段是私有的,那么我们就无法访问并修改它。
所以,我们需要提供访问器方法
。
访问器方法是公共方法,它允许我们读取结构体中的某个或多个私有字段。
这,就是封装
其实这也算是一个面向对象语言的一个很常规的特性了,Java里面就特别强调封装,好像还称为Java Bean?还有各种各样的库方便我们使用封装,比如大名鼎鼎的lombok
(我应该没说错吧…Java并不是学的特别好其实)
OMG,Rust并不像其他语言那样可以创建访问器方法的内置方式,我们必须手动编写它们,因为它们只是常规方法(
练习
这次的练习慢慢的结合之前的学习的内容了,不是那么过分的把读者当傻子那样的简单了(虽然也还是超级简单就对了…
我们要实现三个访问器方法,可以读取Ticket实例的三个私有字段
以下是我的答案:
也是顺利通过了欸
以上就是这一节的学习内容了