116 lines
7.1 KiB
HTML
116 lines
7.1 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>Separating Modules into Different Files</title>
|
||
</head>
|
||
<body>
|
||
<h2 id="separating-modules-into-different-files"><a class="header" href="#separating-modules-into-different-files">Separating Modules into Different Files</a></h2>
|
||
<p>So far, all the examples in this chapter defined multiple modules in one file.
|
||
When modules get large, you might want to move their definitions to a separate
|
||
file to make the code easier to navigate.</p>
|
||
<p>For example, let’s start from the code in Listing 7-17 that had multiple
|
||
restaurant modules. We’ll extract modules into files instead of having all the
|
||
modules defined in the crate root file. In this case, the crate root file is
|
||
<em>src/lib.rs</em>, but this procedure also works with binary crates whose crate root
|
||
file is <em>src/main.rs</em>.</p>
|
||
<p>First, we’ll extract the <code>front_of_house</code> module to its own file. Remove the
|
||
code inside the curly brackets for the <code>front_of_house</code> module, leaving only
|
||
the <code>mod front_of_house;</code> declaration, so that <em>src/lib.rs</em> contains the code
|
||
shown in Listing 7-21. Note that this won’t compile until we create the
|
||
<em>src/front_of_house.rs</em> file in Listing 7-22.</p>
|
||
<figure class="listing" id="listing-7-21">
|
||
<span class="file-name">Filename: src/lib.rs</span>
|
||
<pre><code class="language-rust ignore does_not_compile">mod front_of_house;
|
||
|
||
pub use crate::front_of_house::hosting;
|
||
|
||
pub fn eat_at_restaurant() {
|
||
hosting::add_to_waitlist();
|
||
}</code></pre>
|
||
<figcaption><a href="#listing-7-21">Listing 7-21</a>: Declaring the <code>front_of_house</code> module whose body will be in <em>src/front_of_house.rs</em></figcaption>
|
||
</figure>
|
||
<p>Next, place the code that was in the curly brackets into a new file named
|
||
<em>src/front_of_house.rs</em>, as shown in Listing 7-22. The compiler knows to look
|
||
in this file because it came across the module declaration in the crate root
|
||
with the name <code>front_of_house</code>.</p>
|
||
<figure class="listing" id="listing-7-22">
|
||
<span class="file-name">Filename: src/front_of_house.rs</span>
|
||
<pre><code class="language-rust ignore">pub mod hosting {
|
||
pub fn add_to_waitlist() {}
|
||
}</code></pre>
|
||
<figcaption><a href="#listing-7-22">Listing 7-22</a>: Definitions inside the <code>front_of_house</code> module in <em>src/front_of_house.rs</em></figcaption>
|
||
</figure>
|
||
<p>Note that you only need to load a file using a <code>mod</code> declaration <em>once</em> in your
|
||
module tree. Once the compiler knows the file is part of the project (and knows
|
||
where in the module tree the code resides because of where you’ve put the <code>mod</code>
|
||
statement), other files in your project should refer to the loaded file’s code
|
||
using a path to where it was declared, as covered in the <a href="ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html">“Paths for Referring
|
||
to an Item in the Module Tree”</a><!-- ignore --> section. In other words,
|
||
<code>mod</code> is <em>not</em> an “include” operation that you may have seen in other
|
||
programming languages.</p>
|
||
<p>Next, we’ll extract the <code>hosting</code> module to its own file. The process is a bit
|
||
different because <code>hosting</code> is a child module of <code>front_of_house</code>, not of the
|
||
root module. We’ll place the file for <code>hosting</code> in a new directory that will be
|
||
named for its ancestors in the module tree, in this case <em>src/front_of_house</em>.</p>
|
||
<p>To start moving <code>hosting</code>, we change <em>src/front_of_house.rs</em> to contain only
|
||
the declaration of the <code>hosting</code> module:</p>
|
||
<figure class="listing">
|
||
<span class="file-name">Filename: src/front_of_house.rs</span>
|
||
<pre><code class="language-rust ignore">pub mod hosting;</code></pre>
|
||
</figure>
|
||
<p>Then, we create a <em>src/front_of_house</em> directory and a <em>hosting.rs</em> file to
|
||
contain the definitions made in the <code>hosting</code> module:</p>
|
||
<figure class="listing">
|
||
<span class="file-name">Filename: src/front_of_house/hosting.rs</span>
|
||
<pre><code class="language-rust ignore">pub fn add_to_waitlist() {}</code></pre>
|
||
</figure>
|
||
<p>If we instead put <em>hosting.rs</em> in the <em>src</em> directory, the compiler would
|
||
expect the <em>hosting.rs</em> code to be in a <code>hosting</code> module declared in the crate
|
||
root and not declared as a child of the <code>front_of_house</code> module. The
|
||
compiler’s rules for which files to check for which modules’ code mean the
|
||
directories and files more closely match the module tree.</p>
|
||
<section class="note" aria-role="note">
|
||
<h3 id="alternate-file-paths"><a class="header" href="#alternate-file-paths">Alternate File Paths</a></h3>
|
||
<p>So far we’ve covered the most idiomatic file paths the Rust compiler uses,
|
||
but Rust also supports an older style of file path. For a module named
|
||
<code>front_of_house</code> declared in the crate root, the compiler will look for the
|
||
module’s code in:</p>
|
||
<ul>
|
||
<li><em>src/front_of_house.rs</em> (what we covered)</li>
|
||
<li><em>src/front_of_house/mod.rs</em> (older style, still supported path)</li>
|
||
</ul>
|
||
<p>For a module named <code>hosting</code> that is a submodule of <code>front_of_house</code>, the
|
||
compiler will look for the module’s code in:</p>
|
||
<ul>
|
||
<li><em>src/front_of_house/hosting.rs</em> (what we covered)</li>
|
||
<li><em>src/front_of_house/hosting/mod.rs</em> (older style, still supported path)</li>
|
||
</ul>
|
||
<p>If you use both styles for the same module, you’ll get a compiler error.
|
||
Using a mix of both styles for different modules in the same project is
|
||
allowed but might be confusing for people navigating your project.</p>
|
||
<p>The main downside to the style that uses files named <em>mod.rs</em> is that your
|
||
project can end up with many files named <em>mod.rs</em>, which can get confusing
|
||
when you have them open in your editor at the same time.</p>
|
||
</section>
|
||
<p>We’ve moved each module’s code to a separate file, and the module tree remains
|
||
the same. The function calls in <code>eat_at_restaurant</code> will work without any
|
||
modification, even though the definitions live in different files. This
|
||
technique lets you move modules to new files as they grow in size.</p>
|
||
<p>Note that the <code>pub use crate::front_of_house::hosting</code> statement in
|
||
<em>src/lib.rs</em> also hasn’t changed, nor does <code>use</code> have any impact on what files
|
||
are compiled as part of the crate. The <code>mod</code> keyword declares modules, and Rust
|
||
looks in a file with the same name as the module for the code that goes into
|
||
that module.</p>
|
||
<h2 id="summary"><a class="header" href="#summary">Summary</a></h2>
|
||
<p>Rust lets you split a package into multiple crates and a crate into modules so
|
||
that you can refer to items defined in one module from another module. You can
|
||
do this by specifying absolute or relative paths. These paths can be brought
|
||
into scope with a <code>use</code> statement so that you can use a shorter path for
|
||
multiple uses of the item in that scope. Module code is private by default, but
|
||
you can make definitions public by adding the <code>pub</code> keyword.</p>
|
||
<p>In the next chapter, we’ll look at some collection data structures in the
|
||
standard library that you can use in your neatly organized code.</p>
|
||
</body>
|
||
</html>
|