176 lines
9.5 KiB
HTML
176 lines
9.5 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>Control Scope and Privacy with Modules</title>
|
||
</head>
|
||
<body>
|
||
<!-- Old headings. Do not remove or links may break. -->
|
||
<p><a id="defining-modules-to-control-scope-and-privacy"></a></p>
|
||
<h2 id="control-scope-and-privacy-with-modules"><a class="header" href="#control-scope-and-privacy-with-modules">Control Scope and Privacy with Modules</a></h2>
|
||
<p>In this section, we’ll talk about modules and other parts of the module system,
|
||
namely <em>paths</em>, which allow you to name items; the <code>use</code> keyword that brings a
|
||
path into scope; and the <code>pub</code> keyword to make items public. We’ll also discuss
|
||
the <code>as</code> keyword, external packages, and the glob operator.</p>
|
||
<h3 id="modules-cheat-sheet"><a class="header" href="#modules-cheat-sheet">Modules Cheat Sheet</a></h3>
|
||
<p>Before we get to the details of modules and paths, here we provide a quick
|
||
reference on how modules, paths, the <code>use</code> keyword, and the <code>pub</code> keyword work
|
||
in the compiler, and how most developers organize their code. We’ll be going
|
||
through examples of each of these rules throughout this chapter, but this is a
|
||
great place to refer to as a reminder of how modules work.</p>
|
||
<ul>
|
||
<li><strong>Start from the crate root</strong>: When compiling a crate, the compiler first
|
||
looks in the crate root file (usually <em>src/lib.rs</em> for a library crate and
|
||
<em>src/main.rs</em> for a binary crate) for code to compile.</li>
|
||
<li><strong>Declaring modules</strong>: In the crate root file, you can declare new modules;
|
||
say you declare a “garden” module with <code>mod garden;</code>. The compiler will look
|
||
for the module’s code in these places:
|
||
<ul>
|
||
<li>Inline, within curly brackets that replace the semicolon following <code>mod garden</code></li>
|
||
<li>In the file <em>src/garden.rs</em></li>
|
||
<li>In the file <em>src/garden/mod.rs</em></li>
|
||
</ul>
|
||
</li>
|
||
<li><strong>Declaring submodules</strong>: In any file other than the crate root, you can
|
||
declare submodules. For example, you might declare <code>mod vegetables;</code> in
|
||
<em>src/garden.rs</em>. The compiler will look for the submodule’s code within the
|
||
directory named for the parent module in these places:
|
||
<ul>
|
||
<li>Inline, directly following <code>mod vegetables</code>, within curly brackets instead
|
||
of the semicolon</li>
|
||
<li>In the file <em>src/garden/vegetables.rs</em></li>
|
||
<li>In the file <em>src/garden/vegetables/mod.rs</em></li>
|
||
</ul>
|
||
</li>
|
||
<li><strong>Paths to code in modules</strong>: Once a module is part of your crate, you can
|
||
refer to code in that module from anywhere else in that same crate, as long
|
||
as the privacy rules allow, using the path to the code. For example, an
|
||
<code>Asparagus</code> type in the garden vegetables module would be found at
|
||
<code>crate::garden::vegetables::Asparagus</code>.</li>
|
||
<li><strong>Private vs. public</strong>: Code within a module is private from its parent
|
||
modules by default. To make a module public, declare it with <code>pub mod</code>
|
||
instead of <code>mod</code>. To make items within a public module public as well, use
|
||
<code>pub</code> before their declarations.</li>
|
||
<li><strong>The <code>use</code> keyword</strong>: Within a scope, the <code>use</code> keyword creates shortcuts to
|
||
items to reduce repetition of long paths. In any scope that can refer to
|
||
<code>crate::garden::vegetables::Asparagus</code>, you can create a shortcut with <code>use crate::garden::vegetables::Asparagus;</code>, and from then on you only need to
|
||
write <code>Asparagus</code> to make use of that type in the scope.</li>
|
||
</ul>
|
||
<p>Here, we create a binary crate named <code>backyard</code> that illustrates these rules.
|
||
The crate’s directory, also named <em>backyard</em>, contains these files and
|
||
directories:</p>
|
||
<pre><code class="language-text">backyard
|
||
├── Cargo.lock
|
||
├── Cargo.toml
|
||
└── src
|
||
├── garden
|
||
│ └── vegetables.rs
|
||
├── garden.rs
|
||
└── main.rs
|
||
</code></pre>
|
||
<p>The crate root file in this case is <em>src/main.rs</em>, and it contains:</p>
|
||
<figure class="listing">
|
||
<span class="file-name">Filename: src/main.rs</span>
|
||
<pre><code class="language-rust noplayground ignore">use crate::garden::vegetables::Asparagus;
|
||
|
||
pub mod garden;
|
||
|
||
fn main() {
|
||
let plant = Asparagus {};
|
||
println!("I'm growing {plant:?}!");
|
||
}</code></pre>
|
||
</figure>
|
||
<p>The <code>pub mod garden;</code> line tells the compiler to include the code it finds in
|
||
<em>src/garden.rs</em>, which is:</p>
|
||
<figure class="listing">
|
||
<span class="file-name">Filename: src/garden.rs</span>
|
||
<pre><code class="language-rust noplayground ignore">pub mod vegetables;</code></pre>
|
||
</figure>
|
||
<p>Here, <code>pub mod vegetables;</code> means the code in <em>src/garden/vegetables.rs</em> is
|
||
included too. That code is:</p>
|
||
<pre><code class="language-rust noplayground ignore">#[derive(Debug)]
|
||
pub struct Asparagus {}</code></pre>
|
||
<p>Now let’s get into the details of these rules and demonstrate them in action!</p>
|
||
<h3 id="grouping-related-code-in-modules"><a class="header" href="#grouping-related-code-in-modules">Grouping Related Code in Modules</a></h3>
|
||
<p><em>Modules</em> let us organize code within a crate for readability and easy reuse.
|
||
Modules also allow us to control the <em>privacy</em> of items because code within a
|
||
module is private by default. Private items are internal implementation details
|
||
not available for outside use. We can choose to make modules and the items
|
||
within them public, which exposes them to allow external code to use and depend
|
||
on them.</p>
|
||
<p>As an example, let’s write a library crate that provides the functionality of a
|
||
restaurant. We’ll define the signatures of functions but leave their bodies
|
||
empty to concentrate on the organization of the code rather than the
|
||
implementation of a restaurant.</p>
|
||
<p>In the restaurant industry, some parts of a restaurant are referred to as front
|
||
of house and others as back of house. <em>Front of house</em> is where customers are;
|
||
this encompasses where the hosts seat customers, servers take orders and
|
||
payment, and bartenders make drinks. <em>Back of house</em> is where the chefs and
|
||
cooks work in the kitchen, dishwashers clean up, and managers do administrative
|
||
work.</p>
|
||
<p>To structure our crate in this way, we can organize its functions into nested
|
||
modules. Create a new library named <code>restaurant</code> by running <code>cargo new restaurant --lib</code>. Then, enter the code in Listing 7-1 into <em>src/lib.rs</em> to
|
||
define some modules and function signatures; this code is the front of house
|
||
section.</p>
|
||
<figure class="listing" id="listing-7-1">
|
||
<span class="file-name">Filename: src/lib.rs</span>
|
||
<pre><code class="language-rust noplayground">mod front_of_house {
|
||
mod hosting {
|
||
fn add_to_waitlist() {}
|
||
|
||
fn seat_at_table() {}
|
||
}
|
||
|
||
mod serving {
|
||
fn take_order() {}
|
||
|
||
fn serve_order() {}
|
||
|
||
fn take_payment() {}
|
||
}
|
||
}</code></pre>
|
||
<figcaption><a href="#listing-7-1">Listing 7-1</a>: A <code>front_of_house</code> module containing other modules that then contain functions</figcaption>
|
||
</figure>
|
||
<p>We define a module with the <code>mod</code> keyword followed by the name of the module
|
||
(in this case, <code>front_of_house</code>). The body of the module then goes inside curly
|
||
brackets. Inside modules, we can place other modules, as in this case with the
|
||
modules <code>hosting</code> and <code>serving</code>. Modules can also hold definitions for other
|
||
items, such as structs, enums, constants, traits, and as in Listing 7-1,
|
||
functions.</p>
|
||
<p>By using modules, we can group related definitions together and name why
|
||
they’re related. Programmers using this code can navigate the code based on the
|
||
groups rather than having to read through all the definitions, making it easier
|
||
to find the definitions relevant to them. Programmers adding new functionality
|
||
to this code would know where to place the code to keep the program organized.</p>
|
||
<p>Earlier, we mentioned that <em>src/main.rs</em> and <em>src/lib.rs</em> are called <em>crate
|
||
roots</em>. The reason for their name is that the contents of either of these two
|
||
files form a module named <code>crate</code> at the root of the crate’s module structure,
|
||
known as the <em>module tree</em>.</p>
|
||
<p>Listing 7-2 shows the module tree for the structure in Listing 7-1.</p>
|
||
<figure class="listing" id="listing-7-2">
|
||
<pre><code class="language-text">crate
|
||
└── front_of_house
|
||
├── hosting
|
||
│ ├── add_to_waitlist
|
||
│ └── seat_at_table
|
||
└── serving
|
||
├── take_order
|
||
├── serve_order
|
||
└── take_payment
|
||
</code></pre>
|
||
<figcaption><a href="#listing-7-2">Listing 7-2</a>: The module tree for the code in Listing 7-1</figcaption>
|
||
</figure>
|
||
<p>This tree shows how some of the modules nest inside other modules; for example,
|
||
<code>hosting</code> nests inside <code>front_of_house</code>. The tree also shows that some modules
|
||
are <em>siblings</em>, meaning they’re defined in the same module; <code>hosting</code> and
|
||
<code>serving</code> are siblings defined within <code>front_of_house</code>. If module A is
|
||
contained inside module B, we say that module A is the <em>child</em> of module B and
|
||
that module B is the <em>parent</em> of module A. Notice that the entire module tree
|
||
is rooted under the implicit module named <code>crate</code>.</p>
|
||
<p>The module tree might remind you of the filesystem’s directory tree on your
|
||
computer; this is a very apt comparison! Just like directories in a filesystem,
|
||
you use modules to organize your code. And just like files in a directory, we
|
||
need a way to find our modules.</p>
|
||
</body>
|
||
</html>
|