模块系统
编写大型程序时,组织代码将是很重要的,因为在头脑中保持对整个程序的跟踪将变得不可能。通过对相关功能进行分组,并将具有不同特征的代码分开,你将明确在哪里可以找到实现某个特定功能的代码,以及在哪里可以改变某个功能的工作方式。
到目前为止,我们所写的程序都是在单个文件的单个模块中。随着项目的发展,可以通过把代码分成多个模块,然后再分成多个文件来组织代码。一个 package 可以包含多个二进制 crate,也可以选择一个库 crate。随着 package 的增长,可以将部分内容提取到独立的 crate 中,成为外部依赖。本章涵盖了所有这些技术。对于由一组相互关联的 package 组成的、共同发展的大型项目,Cargo提供了工作空间,我们将在第14章的 “Cargo工作空间” 部分介绍。
除了对功能进行分组外,封装实现细节还可以让你在更高层次上重用代码:一旦你实现了某个操作,其他代码就可以通过代码的 public 接口调用该代码,而不需要知道实现是如何工作的。你写代码的方式定义了哪些部分是 public 的,供其他代码使用,哪些部分是 private 的实现细节,你保留改变的权利。这是另一种限制你必须记在脑子里的细节数量的方法。
scope
是一个相关的概念:编写代码的嵌套上下文有一组被定义为 “in scope” 的名称。在阅读、编写和编译代码时,程序员和编译器需要知道某个特定位置的特定名称是否指的是一个变量、函数、结构体、枚举、模块、常量或其他项目,以及该项目意味着什么。你可以创建作用域并改变哪些名字在作用域内或作用域外。你不能在同一个作用域中有两个同名的项目;有工具可以解决名称冲突。
Rust有很多功能可以让你管理代码组织,包括哪些细节是 public 的,哪些细节是 private 的,以及在程序中每个范围内有哪些名字。这些功能,有时被统称为模块系统,包括:
-
Package: Cargo 的一个功能,可以建立、测试和分享 crate。
-
Crate:一个模块树,产生一个库或可执行文件
-
Module 和 use: 让你控制路径的组织、范围和隐私
-
Path:命名项目的方式,如结构体、函数或模块
在本章中,我们将介绍所有这些功能,讨论它们如何相互作用,并解释如何使用它们来管理范围。到最后,你应该对模块系统有一个扎实的了解,并且能够像专家一样使用作用域。