RustBook/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html

537 lines
43 KiB
HTML
Raw Permalink Normal View History

2020-01-06 20:57:15 +00:00
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Paths for Referring to an Item in the Module Tree - The Rust Programming Language</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="googleFonts/css.css" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
<link rel="stylesheet" href="ferris.css">
<link rel="stylesheet" href="theme/2018-edition.css">
</head>
<body>
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "light" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div id="sidebar-scrollbox" class="sidebar-scrollbox">
<ol class="chapter"><li class="expanded affix "><a href="title-page.html">The Rust Programming Language</a></li><li class="expanded affix "><a href="foreword.html">Foreword</a></li><li class="expanded affix "><a href="ch00-00-introduction.html">Introduction</a></li><li class="expanded "><a href="ch01-00-getting-started.html"><strong aria-hidden="true">1.</strong> Getting Started</a></li><li><ol class="section"><li class="expanded "><a href="ch01-01-installation.html"><strong aria-hidden="true">1.1.</strong> Installation</a></li><li class="expanded "><a href="ch01-02-hello-world.html"><strong aria-hidden="true">1.2.</strong> Hello, World!</a></li><li class="expanded "><a href="ch01-03-hello-cargo.html"><strong aria-hidden="true">1.3.</strong> Hello, Cargo!</a></li></ol></li><li class="expanded "><a href="ch02-00-guessing-game-tutorial.html"><strong aria-hidden="true">2.</strong> Programming a Guessing Game</a></li><li class="expanded "><a href="ch03-00-common-programming-concepts.html"><strong aria-hidden="true">3.</strong> Common Programming Concepts</a></li><li><ol class="section"><li class="expanded "><a href="ch03-01-variables-and-mutability.html"><strong aria-hidden="true">3.1.</strong> Variables and Mutability</a></li><li class="expanded "><a href="ch03-02-data-types.html"><strong aria-hidden="true">3.2.</strong> Data Types</a></li><li class="expanded "><a href="ch03-03-how-functions-work.html"><strong aria-hidden="true">3.3.</strong> Functions</a></li><li class="expanded "><a href="ch03-04-comments.html"><strong aria-hidden="true">3.4.</strong> Comments</a></li><li class="expanded "><a href="ch03-05-control-flow.html"><strong aria-hidden="true">3.5.</strong> Control Flow</a></li></ol></li><li class="expanded "><a href="ch04-00-understanding-ownership.html"><strong aria-hidden="true">4.</strong> Understanding Ownership</a></li><li><ol class="section"><li class="expanded "><a href="ch04-01-what-is-ownership.html"><strong aria-hidden="true">4.1.</strong> What is Ownership?</a></li><li class="expanded "><a href="ch04-02-references-and-borrowing.html"><strong aria-hidden="true">4.2.</strong> References and Borrowing</a></li><li class="expanded "><a href="ch04-03-slices.html"><strong aria-hidden="true">4.3.</strong> The Slice Type</a></li></ol></li><li class="expanded "><a href="ch05-00-structs.html"><strong aria-hidden="true">5.</strong> Using Structs to Structure Related Data</a></li><li><ol class="section"><li class="expanded "><a href="ch05-01-defining-structs.html"><strong aria-hidden="true">5.1.</strong> Defining and Instantiating Structs</a></li><li class="expanded "><a href="ch05-02-example-structs.html"><strong aria-hidden="true">5.2.</strong> An Example Program Using Structs</a></li><li class="expanded "><a href="ch05-03-method-syntax.html"><strong aria-hidden="true">5.3.</strong> Method Syntax</a></li></ol></li><li class="expanded "><a href="ch06-00-enums.html"><strong aria-hidden="true">6.</strong> Enums and Pattern Matching</a></li><li><ol class="section"><li class="expanded "><a href="ch06-01-defining-an-enum.html"><strong aria-hidden="true">6.1.</strong> Defining an Enum</a></li><li class="expanded "><a href="ch06-02-match.html"><strong aria-hidden="true">6.2.</strong> The match Control Flow Operator</a></li><li class="expanded "><a href="ch06-03-if-let.html"><strong aria-hidden="true">6.3.</strong> Concise Control Flow with if let</a></li></ol></li><li class="expanded "><a href="ch07-00-managing-growing-projects-with-packages-crates-and-modules.html"><strong aria-hidden="true">7.</strong> Managing Growing Projects with Packages, Crates, and Modules</a></li><li><ol class="section"><li class="expanded "><a href="ch07-01-packages-and-crates.html"><strong aria-hidden="true">7.1.</strong> Packages and Crates</a></li><li class="expanded "><a href="ch07-02-defining-modules-to-control-scope-and-privacy.html"><strong aria-hidden="true">7.2.</strong> Defining Modules to Control Scope and Privacy</a></li><li class="expanded "><a href="ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html" c
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">The Rust Programming Language</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h2><a class="header" href="#paths-for-referring-to-an-item-in-the-module-tree" id="paths-for-referring-to-an-item-in-the-module-tree">Paths for Referring to an Item in the Module Tree</a></h2>
<p>To show Rust where to find an item in a module tree, we use a path in the same
way we use a path when navigating a filesystem. If we want to call a function,
we need to know its path.</p>
<p>A path can take two forms:</p>
<ul>
<li>An <em>absolute path</em> starts from a crate root by using a crate name or a
literal <code>crate</code>.</li>
<li>A <em>relative path</em> starts from the current module and uses <code>self</code>, <code>super</code>, or
an identifier in the current module.</li>
</ul>
<p>Both absolute and relative paths are followed by one or more identifiers
separated by double colons (<code>::</code>).</p>
<p>Lets return to the example in Listing 7-1. How do we call the
<code>add_to_waitlist</code> function? This is the same as asking, whats the path of the
<code>add_to_waitlist</code> function? In Listing 7-3, we simplified our code a bit by
removing some of the modules and functions. Well show two ways to call the
<code>add_to_waitlist</code> function from a new function <code>eat_at_restaurant</code> defined in
the crate root. The <code>eat_at_restaurant</code> function is part of our library crates
public API, so we mark it with the <code>pub</code> keyword. In the <a href="ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#exposing-paths-with-the-pub-keyword">”Exposing Paths with
the <code>pub</code> Keyword”</a><!-- ignore --> section, well go into more detail
about <code>pub</code>. Note that this example wont compile just yet; well explain why
in a bit.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><code class="language-rust ignore does_not_compile">mod front_of_house {
mod hosting {
fn add_to_waitlist() {}
}
}
pub fn eat_at_restaurant() {
// Absolute path
crate::front_of_house::hosting::add_to_waitlist();
// Relative path
front_of_house::hosting::add_to_waitlist();
}
</code></pre>
<p><span class="caption">Listing 7-3: Calling the <code>add_to_waitlist</code> function using
absolute and relative paths</span></p>
<p>The first time we call the <code>add_to_waitlist</code> function in <code>eat_at_restaurant</code>,
we use an absolute path. The <code>add_to_waitlist</code> function is defined in the same
crate as <code>eat_at_restaurant</code>, which means we can use the <code>crate</code> keyword to
start an absolute path.</p>
<p>After <code>crate</code>, we include each of the successive modules until we make our way
to <code>add_to_waitlist</code>. You can imagine a filesystem with the same structure, and
wed specify the path <code>/front_of_house/hosting/add_to_waitlist</code> to run the
<code>add_to_waitlist</code> program; using the <code>crate</code> name to start from the crate root
is like using <code>/</code> to start from the filesystem root in your shell.</p>
<p>The second time we call <code>add_to_waitlist</code> in <code>eat_at_restaurant</code>, we use a
relative path. The path starts with <code>front_of_house</code>, the name of the module
defined at the same level of the module tree as <code>eat_at_restaurant</code>. Here the
filesystem equivalent would be using the path
<code>front_of_house/hosting/add_to_waitlist</code>. Starting with a name means that the
path is relative.</p>
<p>Choosing whether to use a relative or absolute path is a decision youll make
based on your project. The decision should depend on whether youre more likely
to move item definition code separately from or together with the code that
uses the item. For example, if we move the <code>front_of_house</code> module and the
<code>eat_at_restaurant</code> function into a module named <code>customer_experience</code>, wed
need to update the absolute path to <code>add_to_waitlist</code>, but the relative path
would still be valid. However, if we moved the <code>eat_at_restaurant</code> function
separately into a module named <code>dining</code>, the absolute path to the
<code>add_to_waitlist</code> call would stay the same, but the relative path would need to
be updated. Our preference is to specify absolute paths because its more
likely to move code definitions and item calls independently of each other.</p>
<p>Lets try to compile Listing 7-3 and find out why it wont compile yet! The
error we get is shown in Listing 7-4.</p>
<pre><code class="language-text">$ cargo build
Compiling restaurant v0.1.0 (file:///projects/restaurant)
error[E0603]: module `hosting` is private
--&gt; src/lib.rs:9:28
|
9 | crate::front_of_house::hosting::add_to_waitlist();
| ^^^^^^^
error[E0603]: module `hosting` is private
--&gt; src/lib.rs:12:21
|
12 | front_of_house::hosting::add_to_waitlist();
| ^^^^^^^
</code></pre>
<p><span class="caption">Listing 7-4: Compiler errors from building the code in
Listing 7-3</span></p>
<p>The error messages say that module <code>hosting</code> is private. In other words, we
have the correct paths for the <code>hosting</code> module and the <code>add_to_waitlist</code>
function, but Rust wont let us use them because it doesnt have access to the
private sections.</p>
<p>Modules arent useful only for organizing your code. They also define Rusts
<em>privacy boundary</em>: the line that encapsulates the implementation details
external code isnt allowed to know about, call, or rely on. So, if you want to
make an item like a function or struct private, you put it in a module.</p>
<p>The way privacy works in Rust is that all items (functions, methods, structs,
enums, modules, and constants) are private by default. Items in a parent module
cant use the private items inside child modules, but items in child modules
can use the items in their ancestor modules. The reason is that child modules
wrap and hide their implementation details, but the child modules can see the
context in which theyre defined. To continue with the restaurant metaphor,
think of the privacy rules as being like the back office of a restaurant: what
goes on in there is private to restaurant customers, but office managers can
see and do everything in the restaurant in which they operate.</p>
<p>Rust chose to have the module system function this way so that hiding inner
implementation details is the default. That way, you know which parts of the
inner code you can change without breaking outer code. But you can expose inner
parts of child modules code to outer ancestor modules by using the <code>pub</code>
keyword to make an item public.</p>
<h3><a class="header" href="#exposing-paths-with-the-pub-keyword" id="exposing-paths-with-the-pub-keyword">Exposing Paths with the <code>pub</code> Keyword</a></h3>
<p>Lets return to the error in Listing 7-4 that told us the <code>hosting</code> module is
private. We want the <code>eat_at_restaurant</code> function in the parent module to have
access to the <code>add_to_waitlist</code> function in the child module, so we mark the
<code>hosting</code> module with the <code>pub</code> keyword, as shown in Listing 7-5.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><code class="language-rust ignore does_not_compile">mod front_of_house {
pub mod hosting {
fn add_to_waitlist() {}
}
}
pub fn eat_at_restaurant() {
// Absolute path
crate::front_of_house::hosting::add_to_waitlist();
// Relative path
front_of_house::hosting::add_to_waitlist();
}
</code></pre>
<p><span class="caption">Listing 7-5: Declaring the <code>hosting</code> module as <code>pub</code> to
use it from <code>eat_at_restaurant</code></span></p>
<p>Unfortunately, the code in Listing 7-5 still results in an error, as shown in
Listing 7-6.</p>
<pre><code class="language-text">$ cargo build
Compiling restaurant v0.1.0 (file:///projects/restaurant)
error[E0603]: function `add_to_waitlist` is private
--&gt; src/lib.rs:9:37
|
9 | crate::front_of_house::hosting::add_to_waitlist();
| ^^^^^^^^^^^^^^^
error[E0603]: function `add_to_waitlist` is private
--&gt; src/lib.rs:12:30
|
12 | front_of_house::hosting::add_to_waitlist();
| ^^^^^^^^^^^^^^^
</code></pre>
<p><span class="caption">Listing 7-6: Compiler errors from building the code in
Listing 7-5</span></p>
<p>What happened? Adding the <code>pub</code> keyword in front of <code>mod hosting</code> makes the
module public. With this change, if we can access <code>front_of_house</code>, we can
access <code>hosting</code>. But the <em>contents</em> of <code>hosting</code> are still private; making the
module public doesnt make its contents public. The <code>pub</code> keyword on a module
only lets code in its ancestor modules refer to it.</p>
<p>The errors in Listing 7-6 say that the <code>add_to_waitlist</code> function is private.
The privacy rules apply to structs, enums, functions, and methods as well as
modules.</p>
<p>Lets also make the <code>add_to_waitlist</code> function public by adding the <code>pub</code>
keyword before its definition, as in Listing 7-7.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
pub fn eat_at_restaurant() {
// Absolute path
crate::front_of_house::hosting::add_to_waitlist();
// Relative path
front_of_house::hosting::add_to_waitlist();
}
<span class="boring">fn main() {}
</span></code></pre></pre>
<p><span class="caption">Listing 7-7: Adding the <code>pub</code> keyword to <code>mod hosting</code>
and <code>fn add_to_waitlist</code> lets us call the function from
<code>eat_at_restaurant</code></span></p>
<p>Now the code will compile! Lets look at the absolute and the relative path and
double-check why adding the <code>pub</code> keyword lets us use these paths in
<code>add_to_waitlist</code> with respect to the privacy rules.</p>
<p>In the absolute path, we start with <code>crate</code>, the root of our crates module
tree. Then the <code>front_of_house</code> module is defined in the crate root. The
<code>front_of_house</code> module isnt public, but because the <code>eat_at_restaurant</code>
function is defined in the same module as <code>front_of_house</code> (that is,
<code>eat_at_restaurant</code> and <code>front_of_house</code> are siblings), we can refer to
<code>front_of_house</code> from <code>eat_at_restaurant</code>. Next is the <code>hosting</code> module marked
with <code>pub</code>. We can access the parent module of <code>hosting</code>, so we can access
<code>hosting</code>. Finally, the <code>add_to_waitlist</code> function is marked with <code>pub</code> and we
can access its parent module, so this function call works!</p>
<p>In the relative path, the logic is the same as the absolute path except for the
first step: rather than starting from the crate root, the path starts from
<code>front_of_house</code>. The <code>front_of_house</code> module is defined within the same module
as <code>eat_at_restaurant</code>, so the relative path starting from the module in which
<code>eat_at_restaurant</code> is defined works. Then, because <code>hosting</code> and
<code>add_to_waitlist</code> are marked with <code>pub</code>, the rest of the path works, and this
function call is valid!</p>
<h3><a class="header" href="#starting-relative-paths-with-super" id="starting-relative-paths-with-super">Starting Relative Paths with <code>super</code></a></h3>
<p>We can also construct relative paths that begin in the parent module by using
<code>super</code> at the start of the path. This is like starting a filesystem path with
the <code>..</code> syntax. Why would we want to do this?</p>
<p>Consider the code in Listing 7-8 that models the situation in which a chef
fixes an incorrect order and personally brings it out to the customer. The
function <code>fix_incorrect_order</code> calls the function <code>serve_order</code> by specifying
the path to <code>serve_order</code> starting with <code>super</code>:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">fn serve_order() {}
mod back_of_house {
fn fix_incorrect_order() {
cook_order();
super::serve_order();
}
fn cook_order() {}
}
<span class="boring">fn main() {}
</span></code></pre></pre>
<p><span class="caption">Listing 7-8: Calling a function using a relative path
starting with <code>super</code></span></p>
<p>The <code>fix_incorrect_order</code> function is in the <code>back_of_house</code> module, so we can
use <code>super</code> to go to the parent module of <code>back_of_house</code>, which in this case
is <code>crate</code>, the root. From there, we look for <code>serve_order</code> and find it.
Success! We think the <code>back_of_house</code> module and the <code>serve_order</code> function are
likely to stay in the same relationship to each other and get moved together
should we decide to reorganize the crates module tree. Therefore, we used
<code>super</code> so well have fewer places to update code in the future if this code
gets moved to a different module.</p>
<h3><a class="header" href="#making-structs-and-enums-public" id="making-structs-and-enums-public">Making Structs and Enums Public</a></h3>
<p>We can also use <code>pub</code> to designate structs and enums as public, but there are a
few extra details. If we use <code>pub</code> before a struct definition, we make the
struct public, but the structs fields will still be private. We can make each
field public or not on a case-by-case basis. In Listing 7-9, weve defined a
public <code>back_of_house::Breakfast</code> struct with a public <code>toast</code> field but a
private <code>seasonal_fruit</code> field. This models the case in a restaurant where the
customer can pick the type of bread that comes with a meal, but the chef
decides which fruit accompanies the meal based on whats in season and in
stock. The available fruit changes quickly, so customers cant choose the fruit
or even see which fruit theyll get.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">
<span class="boring">#![allow(unused_variables)]
</span><span class="boring">fn main() {
</span>mod back_of_house {
pub struct Breakfast {
pub toast: String,
seasonal_fruit: String,
}
impl Breakfast {
pub fn summer(toast: &amp;str) -&gt; Breakfast {
Breakfast {
toast: String::from(toast),
seasonal_fruit: String::from(&quot;peaches&quot;),
}
}
}
}
pub fn eat_at_restaurant() {
// Order a breakfast in the summer with Rye toast
let mut meal = back_of_house::Breakfast::summer(&quot;Rye&quot;);
// Change our mind about what bread we'd like
meal.toast = String::from(&quot;Wheat&quot;);
println!(&quot;I'd like {} toast please&quot;, meal.toast);
// The next line won't compile if we uncomment it; we're not allowed
// to see or modify the seasonal fruit that comes with the meal
// meal.seasonal_fruit = String::from(&quot;blueberries&quot;);
}
<span class="boring">}
</span></code></pre></pre>
<p><span class="caption">Listing 7-9: A struct with some public fields and some
private fields</span></p>
<p>Because the <code>toast</code> field in the <code>back_of_house::Breakfast</code> struct is public,
in <code>eat_at_restaurant</code> we can write and read to the <code>toast</code> field using dot
notation. Notice that we cant use the <code>seasonal_fruit</code> field in
<code>eat_at_restaurant</code> because <code>seasonal_fruit</code> is private. Try uncommenting the
line modifying the <code>seasonal_fruit</code> field value to see what error you get!</p>
<p>Also, note that because <code>back_of_house::Breakfast</code> has a private field, the
struct needs to provide a public associated function that constructs an
instance of <code>Breakfast</code> (weve named it <code>summer</code> here). If <code>Breakfast</code> didnt
have such a function, we couldnt create an instance of <code>Breakfast</code> in
<code>eat_at_restaurant</code> because we couldnt set the value of the private
<code>seasonal_fruit</code> field in <code>eat_at_restaurant</code>.</p>
<p>In contrast, if we make an enum public, all of its variants are then public. We
only need the <code>pub</code> before the <code>enum</code> keyword, as shown in Listing 7-10.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">
<span class="boring">#![allow(unused_variables)]
</span><span class="boring">fn main() {
</span>mod back_of_house {
pub enum Appetizer {
Soup,
Salad,
}
}
pub fn eat_at_restaurant() {
let order1 = back_of_house::Appetizer::Soup;
let order2 = back_of_house::Appetizer::Salad;
}
<span class="boring">}
</span></code></pre></pre>
<p><span class="caption">Listing 7-10: Designating an enum as public makes all its
variants public</span></p>
<p>Because we made the <code>Appetizer</code> enum public, we can use the <code>Soup</code> and <code>Salad</code>
variants in <code>eat_at_restaurant</code>. Enums arent very useful unless their variants
are public; it would be annoying to have to annotate all enum variants with
<code>pub</code> in every case, so the default for enum variants is to be public. Structs
are often useful without their fields being public, so struct fields follow the
general rule of everything being private by default unless annotated with <code>pub</code>.</p>
<p>Theres one more situation involving <code>pub</code> that we havent covered, and that is
our last module system feature: the <code>use</code> keyword. Well cover <code>use</code> by itself
first, and then well show how to combine <code>pub</code> and <code>use</code>.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="ch07-02-defining-modules-to-control-scope-and-privacy.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="ch07-04-bringing-paths-into-scope-with-the-use-keyword.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="ch07-02-defining-modules-to-control-scope-and-privacy.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a href="ch07-04-bringing-paths-into-scope-with-the-use-keyword.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script type="text/javascript">
window.playpen_copyable = true;
</script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
<script type="text/javascript" src="ferris.js"></script>
</body>
</html>