库级别的隐私
本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 32 课,共 110 课。
在 Dart 中,隐私是在库级别强制执行的,而不是在类级别。这与 Java 或 C++ 等语言有一个重要区别。在 Dart 中,库通常是单个文件,也可以是通过 part 指令连接起来的多个文件。
私有成员(以 _ 开头的成员)在同一个库中的任何位置都可以访问,包括在其他类中:
// 两个类都在同一个文件中(属于同一个库)
class Engine {
int _horsepower = 200; // 仅限这个库访问
}
class Car {
void showPower(Engine engine) {
print(engine._horsepower); // 可以访问!因为属于同一个库
}
}不过,当你从另一个文件导入一个类时,它的私有成员就会真正隐藏起来:
// 文件:engine.dart
class Engine {
int _horsepower = 200;
int get power => _horsepower;
}
// 文件:main.dart
import 'engine.dart';
void main() {
var engine = Engine();
// print(engine._horsepower); // 错误!无法访问
print(engine.power); // 可以运行:使用公共 getter
}这种库级隐私意味着同一文件中的类可以密切协作,同时仍对外部代码隐藏实现细节。这是一种有意的设计选择,鼓励你将相关的类组织在同一个库中。
挑战
简单我们来构建一个团队协作系统,演示 Dart 中库级隐私的工作方式。你将看到,同一文件中的类可以访问彼此的私有成员,而不同文件中的代码则不能。
你将把代码分成两个文件:
team.dart:这个文件包含两个在同一个库中紧密协作的类:- 一个
Member类,包含公开的String name和私有的int _performanceScore,初始值为50。添加一个接收姓名的构造函数,以及一个返回私有分数的公开 getterperformanceScore。 - 在同一文件中添加一个
TeamLead类,它可以直接访问Member的私有字段(因为它们在同一个库中)。这个类应包含公开的String name、一个接收姓名的构造函数,以及一个方法evaluateMember(Member member)。该方法直接访问member._performanceScore,将它加上10,并打印[leadName] boosted [memberName]'s score to [newScore]。
- 一个
main.dart:导入你的团队文件,并演示访问方式的区别:- 创建一个名为
'Alice'的Member - 创建一个名为
'Bob'的TeamLead - 使用 Alice 的公开 getter 打印
Initial score: [score] - 让 Bob 使用
evaluateMember对 Alice 进行评估 - 使用公开 getter 打印
Updated score: [score] - 打印
Direct access from main: Not allowed(这提醒我们,main.dart不能直接访问_performanceScore,因为它位于另一个库中)
- 创建一个名为
这里的关键点是,TeamLead 可以直接读取和修改 Member 的私有 _performanceScore,因为这两个类都位于同一个文件中(也就是同一个库中)。不过,main.dart 中的代码必须使用公开 getter,因为它位于另一个库中。
预期输出:
Initial score: 50
Bob boosted Alice's score to 60
Updated score: 60
Direct access from main: Not allowed亲手试试
import 'team.dart';
void main() {
// TODO: 创建一个名为 'Alice' 的 Member
// TODO: 创建一个名为 'Bob' 的 TeamLead
// TODO: 使用 Alice 的公共 getter 打印 "Initial score: [score]"
// TODO: 让 Bob 使用 evaluateMember 评估 Alice
// TODO: 使用公共 getter 打印 "Updated score: [score]"
// TODO: 打印 "Direct access from main: Not allowed"
// 注意:这里无法访问 alice._performanceScore,因为
// main.dart 和 team.dart 属于不同的库
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Dart 在线编译器