RustBook/ch10-02-traits.html
2020-01-06 21:57:15 +01:00

745 lines
55 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Traits: Defining Shared Behavior - 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"><strong aria-hidden="true">7.3.</strong> Paths for Referring to an Item in the Module Tree</a></li><li class="expanded "><a href="ch07-04-bringing-paths-into-scope-with-the-use-keyword.html"><strong aria-hidden="true">7.4.</strong> Bringing Paths Into Scope with the use Keyword</a></li><li class="expanded "><a href="ch07-05-separating-modules-into-different-files.html"><strong aria-hidden="true">7.5.</strong> Separating Modules into Different Files</a></li></ol></li><li class="expanded "><a href="ch08-00-common-collections.html"><strong aria-hidden="true">8.</strong> Common Collections</a></li><li><ol class="section"><li class="expanded "><a href="ch08-01-vectors.html"><strong aria-hidden="true">8.1.</strong> Storing Lists of Values with Vectors</a></li><li class="expanded "><a href="ch08-02-strings.html"><strong aria-hidden="true">8.2.</strong> Storing UTF-8 Encoded Text with Strings</a></li><li class="expanded "><a href="ch08-03-hash-maps.html"><strong aria-hidden="true">8.3.</strong> Storing Keys with Associated Values in Hash Maps</a></li></ol></li><li class="expanded "><a href="ch09-00-error-handling.html"><strong aria-hidden="true">9.</strong> Error Handling</a></li><li><ol class="section"><li class="expanded "><a href="ch09-01-unrecoverable-errors-with-panic.html"><strong aria-hidden="true">9.1.</strong> Unrecoverable Errors with panic!</a></li><li class="expanded "><a href="ch09-02-recoverable-errors-with-result.html"><strong aria-hidden="true">9.2.</strong> Recoverable Errors with Result</a></li><li class="expanded "><a href="ch09-03-to-panic-or-not-to-panic.html"><strong aria-hidden="true">9.3.</strong> To panic! or Not To panic!</a></li></ol></li><li class="expanded "><a href="ch10-00-generics.html"><strong aria-hidden="true">10.</strong> Generic Types, Traits, and Lifetimes</a></li><li><ol class="section"><li class="expanded "><a href="ch10-01-syntax.html"><strong aria-hidden="true">10.1.</strong> Generic Data Types</a></li><li class="expanded "><a href="ch10-02-traits.html" class="active"><strong aria-hidden="true">10.2.</strong> Traits: Defining Shared Behavior</a></li><li class="expanded "><a href="ch10-03-lifetime-syntax.html"><strong aria-hidden="true">10.3.</strong> Validating References with Lifetimes</a></li></ol></li><li class="expanded "><a href="ch11-00-testing.html"><strong aria-hidden="true">11.</strong> Writing Automated Tests</a></li><li><ol class="section"><li class="expanded "><a href="ch11-01-writing-tests.html"><strong aria-hidden="true">11.1.</strong> How to Write Tests</a></li><li class="expanded "><a href="ch11-02-running-tests.html"><strong aria-hidden="true">11.2.</strong> Controlling How Tests Are Run</a></li><li class="expanded "><a href="ch11-03-test-organization.html"><strong aria-hidden="true">11.3.</strong> Test Organization</a></li></ol></li><li class="expanded "><a href="ch12-00-an-io-project.html"><strong aria-hidden="true">12.</strong> An I/O Project: Building a Command Line Program</a></li><li><ol class="section"><li class="expanded "><a href="ch12-01-accepting-command-line-arguments.html"><strong aria-hidden="true">12.1.</strong> Accepting Command Line Arguments</a></li><li class="expanded "><a href="ch12-02-reading-a-file.html"><strong aria-hidden="true">12.2.</strong> Reading a File</a></li><li class="expanded "><a href="ch12-03-improving-error-handling-and-modularity.html"><strong aria-hidden="true">12.3.</strong> Refactoring to Improve Modularity and Error Handling</a></li><li class="expanded "><a href="ch12-04-testing-the-librarys-functionality.html"><strong aria-hidden="true">12.4.</strong> Developing the Librarys Functionality with Test Driven Development</a></li><li class="expanded "><a href="ch12-05-working-with-environment-variables.html"><strong aria-hidden="true">12.5.</strong> Working with Environment Variables</a></li><li class="expanded "><a href="ch12-06-writing-to-stderr-instead-of-stdout.html"><strong aria-hidden="true">12.6.</strong> Writing Error Messages to Standard Error Instead of Standard Output</a></li></ol></li><li class="expanded "><a href="ch13-00-functional-features.html"><strong aria-hidden="true">13.</strong> Functional Language Features: Iterators and Closures</a></li><li><ol class="section"><li class="expanded "><a href="ch13-01-closures.html"><strong aria-hidden="true">13.1.</strong> Closures: Anonymous Functions that Can Capture Their Environment</a></li><li class="expanded "><a href="ch13-02-iterators.html"><strong aria-hidden="true">13.2.</strong> Processing a Series of Items with Iterators</a></li><li class="expanded "><a href="ch13-03-improving-our-io-project.html"><strong aria-hidden="true">13.3.</strong> Improving Our I/O Project</a></li><li class="expanded "><a href="ch13-04-performance.html"><strong aria-hidden="true">13.4.</strong> Comparing Performance: Loops vs. Iterators</a></li></ol></li><li class="expanded "><a href="ch14-00-more-about-cargo.html"><strong aria-hidden="true">14.</strong> More about Cargo and Crates.io</a></li><li><ol class="section"><li class="expanded "><a href="ch14-01-release-profiles.html"><strong aria-hidden="true">14.1.</strong> Customizing Builds with Release Profiles</a></li><li class="expanded "><a href="ch14-02-publishing-to-crates-io.html"><strong aria-hidden="true">14.2.</strong> Publishing a Crate to Crates.io</a></li><li class="expanded "><a href="ch14-03-cargo-workspaces.html"><strong aria-hidden="true">14.3.</strong> Cargo Workspaces</a></li><li class="expanded "><a href="ch14-04-installing-binaries.html"><strong aria-hidden="true">14.4.</strong> Installing Binaries from Crates.io with cargo install</a></li><li class="expanded "><a href="ch14-05-extending-cargo.html"><strong aria-hidden="true">14.5.</strong> Extending Cargo with Custom Commands</a></li></ol></li><li class="expanded "><a href="ch15-00-smart-pointers.html"><strong aria-hidden="true">15.</strong> Smart Pointers</a></li><li><ol class="section"><li class="expanded "><a href="ch15-01-box.html"><strong aria-hidden="true">15.1.</strong> Using Box<T> to Point to Data on the Heap</a></li><li class="expanded "><a href="ch15-02-deref.html"><strong aria-hidden="true">15.2.</strong> Treating Smart Pointers Like Regular References with the Deref Trait</a></li><li class="expanded "><a href="ch15-03-drop.html"><strong aria-hidden="true">15.3.</strong> Running Code on Cleanup with the Drop Trait</a></li><li class="expanded "><a href="ch15-04-rc.html"><strong aria-hidden="true">15.4.</strong> Rc<T>, the Reference Counted Smart Pointer</a></li><li class="expanded "><a href="ch15-05-interior-mutability.html"><strong aria-hidden="true">15.5.</strong> RefCell<T> and the Interior Mutability Pattern</a></li><li class="expanded "><a href="ch15-06-reference-cycles.html"><strong aria-hidden="true">15.6.</strong> Reference Cycles Can Leak Memory</a></li></ol></li><li class="expanded "><a href="ch16-00-concurrency.html"><strong aria-hidden="true">16.</strong> Fearless Concurrency</a></li><li><ol class="section"><li class="expanded "><a href="ch16-01-threads.html"><strong aria-hidden="true">16.1.</strong> Using Threads to Run Code Simultaneously</a></li><li class="expanded "><a href="ch16-02-message-passing.html"><strong aria-hidden="true">16.2.</strong> Using Message Passing to Transfer Data Between Threads</a></li><li class="expanded "><a href="ch16-03-shared-state.html"><strong aria-hidden="true">16.3.</strong> Shared-State Concurrency</a></li><li class="expanded "><a href="ch16-04-extensible-concurrency-sync-and-send.html"><strong aria-hidden="true">16.4.</strong> Extensible Concurrency with the Sync and Send Traits</a></li></ol></li><li class="expanded "><a href="ch17-00-oop.html"><strong aria-hidden="true">17.</strong> Object Oriented Programming Features of Rust</a></li><li><ol class="section"><li class="expanded "><a href="ch17-01-what-is-oo.html"><strong aria-hidden="true">17.1.</strong> Characteristics of Object-Oriented Languages</a></li><li class="expanded "><a href="ch17-02-trait-objects.html"><strong aria-hidden="true">17.2.</strong> Using Trait Objects That Allow for Values of Different Types</a></li><li class="expanded "><a href="ch17-03-oo-design-patterns.html"><strong aria-hidden="true">17.3.</strong> Implementing an Object-Oriented Design Pattern</a></li></ol></li><li class="expanded "><a href="ch18-00-patterns.html"><strong aria-hidden="true">18.</strong> Patterns and Matching</a></li><li><ol class="section"><li class="expanded "><a href="ch18-01-all-the-places-for-patterns.html"><strong aria-hidden="true">18.1.</strong> All the Places Patterns Can Be Used</a></li><li class="expanded "><a href="ch18-02-refutability.html"><strong aria-hidden="true">18.2.</strong> Refutability: Whether a Pattern Might Fail to Match</a></li><li class="expanded "><a href="ch18-03-pattern-syntax.html"><strong aria-hidden="true">18.3.</strong> Pattern Syntax</a></li></ol></li><li class="expanded "><a href="ch19-00-advanced-features.html"><strong aria-hidden="true">19.</strong> Advanced Features</a></li><li><ol class="section"><li class="expanded "><a href="ch19-01-unsafe-rust.html"><strong aria-hidden="true">19.1.</strong> Unsafe Rust</a></li><li class="expanded "><a href="ch19-03-advanced-traits.html"><strong aria-hidden="true">19.2.</strong> Advanced Traits</a></li><li class="expanded "><a href="ch19-04-advanced-types.html"><strong aria-hidden="true">19.3.</strong> Advanced Types</a></li><li class="expanded "><a href="ch19-05-advanced-functions-and-closures.html"><strong aria-hidden="true">19.4.</strong> Advanced Functions and Closures</a></li><li class="expanded "><a href="ch19-06-macros.html"><strong aria-hidden="true">19.5.</strong> Macros</a></li></ol></li><li class="expanded "><a href="ch20-00-final-project-a-web-server.html"><strong aria-hidden="true">20.</strong> Final Project: Building a Multithreaded Web Server</a></li><li><ol class="section"><li class="expanded "><a href="ch20-01-single-threaded.html"><strong aria-hidden="true">20.1.</strong> Building a Single-Threaded Web Server</a></li><li class="expanded "><a href="ch20-02-multithreaded.html"><strong aria-hidden="true">20.2.</strong> Turning Our Single-Threaded Server into a Multithreaded Server</a></li><li class="expanded "><a href="ch20-03-graceful-shutdown-and-cleanup.html"><strong aria-hidden="true">20.3.</strong> Graceful Shutdown and Cleanup</a></li></ol></li><li class="expanded "><a href="appendix-00.html"><strong aria-hidden="true">21.</strong> Appendix</a></li><li><ol class="section"><li class="expanded "><a href="appendix-01-keywords.html"><strong aria-hidden="true">21.1.</strong> A - Keywords</a></li><li class="expanded "><a href="appendix-02-operators.html"><strong aria-hidden="true">21.2.</strong> B - Operators and Symbols</a></li><li class="expanded "><a href="appendix-03-derivable-traits.html"><strong aria-hidden="true">21.3.</strong> C - Derivable Traits</a></li><li class="expanded "><a href="appendix-04-useful-development-tools.html"><strong aria-hidden="true">21.4.</strong> D - Useful Development Tools</a></li><li class="expanded "><a href="appendix-05-editions.html"><strong aria-hidden="true">21.5.</strong> E - Editions</a></li><li class="expanded "><a href="appendix-06-translation.html"><strong aria-hidden="true">21.6.</strong> F - Translations of the Book</a></li><li class="expanded "><a href="appendix-07-nightly-rust.html"><strong aria-hidden="true">21.7.</strong> G - How Rust is Made and “Nightly Rust”</a></li></ol></li></ol>
</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="#traits-defining-shared-behavior" id="traits-defining-shared-behavior">Traits: Defining Shared Behavior</a></h2>
<p>A <em>trait</em> tells the Rust compiler about functionality a particular type has and
can share with other types. We can use traits to define shared behavior in an
abstract way. We can use trait bounds to specify that a generic can be any type
that has certain behavior.</p>
<blockquote>
<p>Note: Traits are similar to a feature often called <em>interfaces</em> in other
languages, although with some differences.</p>
</blockquote>
<h3><a class="header" href="#defining-a-trait" id="defining-a-trait">Defining a Trait</a></h3>
<p>A types behavior consists of the methods we can call on that type. Different
types share the same behavior if we can call the same methods on all of those
types. Trait definitions are a way to group method signatures together to
define a set of behaviors necessary to accomplish some purpose.</p>
<p>For example, lets say we have multiple structs that hold various kinds and
amounts of text: a <code>NewsArticle</code> struct that holds a news story filed in a
particular location and a <code>Tweet</code> that can have at most 280 characters along
with metadata that indicates whether it was a new tweet, a retweet, or a reply
to another tweet.</p>
<p>We want to make a media aggregator library that can display summaries of data
that might be stored in a <code>NewsArticle</code> or <code>Tweet</code> instance. To do this, we
need a summary from each type, and we need to request that summary by calling a
<code>summarize</code> method on an instance. Listing 10-12 shows the definition of a
<code>Summary</code> trait that expresses this behavior.</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>pub trait Summary {
fn summarize(&amp;self) -&gt; String;
}
<span class="boring">}
</span></code></pre></pre>
<p><span class="caption">Listing 10-12: A <code>Summary</code> trait that consists of the
behavior provided by a <code>summarize</code> method</span></p>
<p>Here, we declare a trait using the <code>trait</code> keyword and then the traits name,
which is <code>Summary</code> in this case. Inside the curly brackets, we declare the
method signatures that describe the behaviors of the types that implement this
trait, which in this case is <code>fn summarize(&amp;self) -&gt; String</code>.</p>
<p>After the method signature, instead of providing an implementation within curly
brackets, we use a semicolon. Each type implementing this trait must provide
its own custom behavior for the body of the method. The compiler will enforce
that any type that has the <code>Summary</code> trait will have the method <code>summarize</code>
defined with this signature exactly.</p>
<p>A trait can have multiple methods in its body: the method signatures are listed
one per line and each line ends in a semicolon.</p>
<h3><a class="header" href="#implementing-a-trait-on-a-type" id="implementing-a-trait-on-a-type">Implementing a Trait on a Type</a></h3>
<p>Now that weve defined the desired behavior using the <code>Summary</code> trait, we can
implement it on the types in our media aggregator. Listing 10-13 shows an
implementation of the <code>Summary</code> trait on the <code>NewsArticle</code> struct that uses the
headline, the author, and the location to create the return value of
<code>summarize</code>. For the <code>Tweet</code> struct, we define <code>summarize</code> as the username
followed by the entire text of the tweet, assuming that tweet content is
already limited to 280 characters.</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><span class="boring">pub trait Summary {
</span><span class="boring"> fn summarize(&amp;self) -&gt; String;
</span><span class="boring">}
</span><span class="boring">
</span>pub struct NewsArticle {
pub headline: String,
pub location: String,
pub author: String,
pub content: String,
}
impl Summary for NewsArticle {
fn summarize(&amp;self) -&gt; String {
format!(&quot;{}, by {} ({})&quot;, self.headline, self.author, self.location)
}
}
pub struct Tweet {
pub username: String,
pub content: String,
pub reply: bool,
pub retweet: bool,
}
impl Summary for Tweet {
fn summarize(&amp;self) -&gt; String {
format!(&quot;{}: {}&quot;, self.username, self.content)
}
}
<span class="boring">}
</span></code></pre></pre>
<p><span class="caption">Listing 10-13: Implementing the <code>Summary</code> trait on the
<code>NewsArticle</code> and <code>Tweet</code> types</span></p>
<p>Implementing a trait on a type is similar to implementing regular methods. The
difference is that after <code>impl</code>, we put the trait name that we want to
implement, then use the <code>for</code> keyword, and then specify the name of the type we
want to implement the trait for. Within the <code>impl</code> block, we put the method
signatures that the trait definition has defined. Instead of adding a semicolon
after each signature, we use curly brackets and fill in the method body with
the specific behavior that we want the methods of the trait to have for the
particular type.</p>
<p>After implementing the trait, we can call the methods on instances of
<code>NewsArticle</code> and <code>Tweet</code> in the same way we call regular methods, like this:</p>
<pre><code class="language-rust ignore">let tweet = Tweet {
username: String::from(&quot;horse_ebooks&quot;),
content: String::from(&quot;of course, as you probably already know, people&quot;),
reply: false,
retweet: false,
};
println!(&quot;1 new tweet: {}&quot;, tweet.summarize());
</code></pre>
<p>This code prints <code>1 new tweet: horse_ebooks: of course, as you probably already know, people</code>.</p>
<p>Note that because we defined the <code>Summary</code> trait and the <code>NewsArticle</code> and
<code>Tweet</code> types in the same <em>lib.rs</em> in Listing 10-13, theyre all in the same
scope. Lets say this <em>lib.rs</em> is for a crate weve called <code>aggregator</code> and
someone else wants to use our crates functionality to implement the <code>Summary</code>
trait on a struct defined within their librarys scope. They would need to
bring the trait into their scope first. They would do so by specifying <code>use aggregator::Summary;</code>, which then would enable them to implement <code>Summary</code> for
their type. The <code>Summary</code> trait would also need to be a public trait for
another crate to implement it, which it is because we put the <code>pub</code> keyword
before <code>trait</code> in Listing 10-12.</p>
<p>One restriction to note with trait implementations is that we can implement a
trait on a type only if either the trait or the type is local to our crate.
For example, we can implement standard library traits like <code>Display</code> on a
custom type like <code>Tweet</code> as part of our <code>aggregator</code> crate functionality,
because the type <code>Tweet</code> is local to our <code>aggregator</code> crate. We can also
implement <code>Summary</code> on <code>Vec&lt;T&gt;</code> in our <code>aggregator</code> crate, because the
trait <code>Summary</code> is local to our <code>aggregator</code> crate.</p>
<p>But we cant implement external traits on external types. For example, we cant
implement the <code>Display</code> trait on <code>Vec&lt;T&gt;</code> within our <code>aggregator</code> crate,
because <code>Display</code> and <code>Vec&lt;T&gt;</code> are defined in the standard library and arent
local to our <code>aggregator</code> crate. This restriction is part of a property of
programs called <em>coherence</em>, and more specifically the <em>orphan rule</em>, so named
because the parent type is not present. This rule ensures that other peoples
code cant break your code and vice versa. Without the rule, two crates could
implement the same trait for the same type, and Rust wouldnt know which
implementation to use.</p>
<h3><a class="header" href="#default-implementations" id="default-implementations">Default Implementations</a></h3>
<p>Sometimes its useful to have default behavior for some or all of the methods
in a trait instead of requiring implementations for all methods on every type.
Then, as we implement the trait on a particular type, we can keep or override
each methods default behavior.</p>
<p>Listing 10-14 shows how to specify a default string for the <code>summarize</code> method
of the <code>Summary</code> trait instead of only defining the method signature, as we did
in Listing 10-12.</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>pub trait Summary {
fn summarize(&amp;self) -&gt; String {
String::from(&quot;(Read more...)&quot;)
}
}
<span class="boring">}
</span></code></pre></pre>
<p><span class="caption">Listing 10-14: Definition of a <code>Summary</code> trait with a
default implementation of the <code>summarize</code> method</span></p>
<p>To use a default implementation to summarize instances of <code>NewsArticle</code> instead
of defining a custom implementation, we specify an empty <code>impl</code> block with
<code>impl Summary for NewsArticle {}</code>.</p>
<p>Even though were no longer defining the <code>summarize</code> method on <code>NewsArticle</code>
directly, weve provided a default implementation and specified that
<code>NewsArticle</code> implements the <code>Summary</code> trait. As a result, we can still call
the <code>summarize</code> method on an instance of <code>NewsArticle</code>, like this:</p>
<pre><code class="language-rust ignore">let article = NewsArticle {
headline: String::from(&quot;Penguins win the Stanley Cup Championship!&quot;),
location: String::from(&quot;Pittsburgh, PA, USA&quot;),
author: String::from(&quot;Iceburgh&quot;),
content: String::from(&quot;The Pittsburgh Penguins once again are the best
hockey team in the NHL.&quot;),
};
println!(&quot;New article available! {}&quot;, article.summarize());
</code></pre>
<p>This code prints <code>New article available! (Read more...)</code>.</p>
<p>Creating a default implementation for <code>summarize</code> doesnt require us to change
anything about the implementation of <code>Summary</code> on <code>Tweet</code> in Listing 10-13. The
reason is that the syntax for overriding a default implementation is the same
as the syntax for implementing a trait method that doesnt have a default
implementation.</p>
<p>Default implementations can call other methods in the same trait, even if those
other methods dont have a default implementation. In this way, a trait can
provide a lot of useful functionality and only require implementors to specify
a small part of it. For example, we could define the <code>Summary</code> trait to have a
<code>summarize_author</code> method whose implementation is required, and then define a
<code>summarize</code> method that has a default implementation that calls the
<code>summarize_author</code> method:</p>
<pre><pre class="playpen"><code class="language-rust">
<span class="boring">#![allow(unused_variables)]
</span><span class="boring">fn main() {
</span>pub trait Summary {
fn summarize_author(&amp;self) -&gt; String;
fn summarize(&amp;self) -&gt; String {
format!(&quot;(Read more from {}...)&quot;, self.summarize_author())
}
}
<span class="boring">}
</span></code></pre></pre>
<p>To use this version of <code>Summary</code>, we only need to define <code>summarize_author</code>
when we implement the trait on a type:</p>
<pre><code class="language-rust ignore">impl Summary for Tweet {
fn summarize_author(&amp;self) -&gt; String {
format!(&quot;@{}&quot;, self.username)
}
}
</code></pre>
<p>After we define <code>summarize_author</code>, we can call <code>summarize</code> on instances of the
<code>Tweet</code> struct, and the default implementation of <code>summarize</code> will call the
definition of <code>summarize_author</code> that weve provided. Because weve implemented
<code>summarize_author</code>, the <code>Summary</code> trait has given us the behavior of the
<code>summarize</code> method without requiring us to write any more code.</p>
<pre><code class="language-rust ignore">let tweet = Tweet {
username: String::from(&quot;horse_ebooks&quot;),
content: String::from(&quot;of course, as you probably already know, people&quot;),
reply: false,
retweet: false,
};
println!(&quot;1 new tweet: {}&quot;, tweet.summarize());
</code></pre>
<p>This code prints <code>1 new tweet: (Read more from @horse_ebooks...)</code>.</p>
<p>Note that it isnt possible to call the default implementation from an
overriding implementation of that same method.</p>
<h3><a class="header" href="#traits-as-parameters" id="traits-as-parameters">Traits as Parameters</a></h3>
<p>Now that you know how to define and implement traits, we can explore how to use
traits to define functions that accept many different types.</p>
<p>For example, in Listing 10-13, we implemented the <code>Summary</code> trait on the
<code>NewsArticle</code> and <code>Tweet</code> types. We can define a <code>notify</code> function that calls
the <code>summarize</code> method on its <code>item</code> parameter, which is of some type that
implements the <code>Summary</code> trait. To do this, we can use the <code>impl Trait</code>
syntax, like this:</p>
<pre><code class="language-rust ignore">pub fn notify(item: impl Summary) {
println!(&quot;Breaking news! {}&quot;, item.summarize());
}
</code></pre>
<p>Instead of a concrete type for the <code>item</code> parameter, we specify the <code>impl</code>
keyword and the trait name. This parameter accepts any type that implements the
specified trait. In the body of <code>notify</code>, we can call any methods on <code>item</code>
that come from the <code>Summary</code> trait, such as <code>summarize</code>. We can call <code>notify</code>
and pass in any instance of <code>NewsArticle</code> or <code>Tweet</code>. Code that calls the
function with any other type, such as a <code>String</code> or an <code>i32</code>, wont compile
because those types dont implement <code>Summary</code>.</p>
<h4><a class="header" href="#trait-bound-syntax" id="trait-bound-syntax">Trait Bound Syntax</a></h4>
<p>The <code>impl Trait</code> syntax works for straightforward cases but is actually
syntax sugar for a longer form, which is called a <em>trait bound</em>; it looks like
this:</p>
<pre><code class="language-rust ignore">pub fn notify&lt;T: Summary&gt;(item: T) {
println!(&quot;Breaking news! {}&quot;, item.summarize());
}
</code></pre>
<p>This longer form is equivalent to the example in the previous section but is
more verbose. We place trait bounds with the declaration of the generic type
parameter after a colon and inside angle brackets.</p>
<p>The <code>impl Trait</code> syntax is convenient and makes for more concise code in simple
cases. The trait bound syntax can express more complexity in other cases. For
example, we can have two parameters that implement <code>Summary</code>. Using the <code>impl Trait</code> syntax looks like this:</p>
<pre><code class="language-rust ignore">pub fn notify(item1: impl Summary, item2: impl Summary) {
</code></pre>
<p>If we wanted this function to allow <code>item1</code> and <code>item2</code> to have different
types, using <code>impl Trait</code> would be appropriate (as long as both types implement
<code>Summary</code>). If we wanted to force both parameters to have the same type, thats
only possible to express using a trait bound, like this:</p>
<pre><code class="language-rust ignore">pub fn notify&lt;T: Summary&gt;(item1: T, item2: T) {
</code></pre>
<p>The generic type <code>T</code> specified as the type of the <code>item1</code> and <code>item2</code>
parameters constrains the function such that the concrete type of the value
passed as an argument for <code>item1</code> and <code>item2</code> must be the same.</p>
<h4><a class="header" href="#specifying-multiple-trait-bounds-with-the--syntax" id="specifying-multiple-trait-bounds-with-the--syntax">Specifying Multiple Trait Bounds with the <code>+</code> Syntax</a></h4>
<p>We can also specify more than one trait bound. Say we wanted <code>notify</code> to use
display formatting on <code>item</code> as well as the <code>summarize</code> method: we specify in
the <code>notify</code> definition that <code>item</code> must implement both <code>Display</code> and
<code>Summary</code>. We can do so using the <code>+</code> syntax:</p>
<pre><code class="language-rust ignore">pub fn notify(item: impl Summary + Display) {
</code></pre>
<p>The <code>+</code> syntax is also valid with trait bounds on generic types:</p>
<pre><code class="language-rust ignore">pub fn notify&lt;T: Summary + Display&gt;(item: T) {
</code></pre>
<p>With the two trait bounds specified, the body of <code>notify</code> can call <code>summarize</code>
and use <code>{}</code> to format <code>item</code>.</p>
<h4><a class="header" href="#clearer-trait-bounds-with-where-clauses" id="clearer-trait-bounds-with-where-clauses">Clearer Trait Bounds with <code>where</code> Clauses</a></h4>
<p>Using too many trait bounds has its downsides. Each generic has its own trait
bounds, so functions with multiple generic type parameters can contain lots of
trait bound information between the functions name and its parameter list,
making the function signature hard to read. For this reason, Rust has alternate
syntax for specifying trait bounds inside a <code>where</code> clause after the function
signature. So instead of writing this:</p>
<pre><code class="language-rust ignore">fn some_function&lt;T: Display + Clone, U: Clone + Debug&gt;(t: T, u: U) -&gt; i32 {
</code></pre>
<p>we can use a <code>where</code> clause, like this:</p>
<pre><code class="language-rust ignore">fn some_function&lt;T, U&gt;(t: T, u: U) -&gt; i32
where T: Display + Clone,
U: Clone + Debug
{
</code></pre>
<p>This functions signature is less cluttered: the function name, parameter list,
and return type are close together, similar to a function without lots of trait
bounds.</p>
<h3><a class="header" href="#returning-types-that-implement-traits" id="returning-types-that-implement-traits">Returning Types that Implement Traits</a></h3>
<p>We can also use the <code>impl Trait</code> syntax in the return position to return a
value of some type that implements a trait, as shown here:</p>
<pre><code class="language-rust ignore">fn returns_summarizable() -&gt; impl Summary {
Tweet {
username: String::from(&quot;horse_ebooks&quot;),
content: String::from(&quot;of course, as you probably already know, people&quot;),
reply: false,
retweet: false,
}
}
</code></pre>
<p>By using <code>impl Summary</code> for the return type, we specify that the
<code>returns_summarizable</code> function returns some type that implements the <code>Summary</code>
trait without naming the concrete type. In this case, <code>returns_summarizable</code>
returns a <code>Tweet</code>, but the code calling this function doesnt know that.</p>
<p>The ability to return a type that is only specified by the trait it implements
is especially useful in the context of closures and iterators, which we cover
in Chapter 13. Closures and iterators create types that only the compiler knows
or types that are very long to specify. The <code>impl Trait</code> syntax lets you
concisely specify that a function returns some type that implements the
<code>Iterator</code> trait without needing to write out a very long type.</p>
<p>However, you can only use <code>impl Trait</code> if youre returning a single type. For
example, this code that returns either a <code>NewsArticle</code> or a <code>Tweet</code> with the
return type specified as <code>impl Summary</code> wouldnt work:</p>
<pre><code class="language-rust ignore does_not_compile">fn returns_summarizable(switch: bool) -&gt; impl Summary {
if switch {
NewsArticle {
headline: String::from(&quot;Penguins win the Stanley Cup Championship!&quot;),
location: String::from(&quot;Pittsburgh, PA, USA&quot;),
author: String::from(&quot;Iceburgh&quot;),
content: String::from(&quot;The Pittsburgh Penguins once again are the best
hockey team in the NHL.&quot;),
}
} else {
Tweet {
username: String::from(&quot;horse_ebooks&quot;),
content: String::from(&quot;of course, as you probably already know, people&quot;),
reply: false,
retweet: false,
}
}
}
</code></pre>
<p>Returning either a <code>NewsArticle</code> or a <code>Tweet</code> isnt allowed due to restrictions
around how the <code>impl Trait</code> syntax is implemented in the compiler. Well cover
how to write a function with this behavior in the <a href="ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types">“Using Trait Objects That
Allow for Values of Different
Types”</a><!--
ignore --> section of Chapter 17.</p>
<h3><a class="header" href="#fixing-the-largest-function-with-trait-bounds" id="fixing-the-largest-function-with-trait-bounds">Fixing the <code>largest</code> Function with Trait Bounds</a></h3>
<p>Now that you know how to specify the behavior you want to use using the generic
type parameters bounds, lets return to Listing 10-5 to fix the definition of
the <code>largest</code> function that uses a generic type parameter! Last time we tried
to run that code, we received this error:</p>
<pre><code class="language-text">error[E0369]: binary operation `&gt;` cannot be applied to type `T`
--&gt; src/main.rs:5:12
|
5 | if item &gt; largest {
| ^^^^^^^^^^^^^^
|
= note: an implementation of `std::cmp::PartialOrd` might be missing for `T`
</code></pre>
<p>In the body of <code>largest</code> we wanted to compare two values of type <code>T</code> using the
greater than (<code>&gt;</code>) operator. Because that operator is defined as a default
method on the standard library trait <code>std::cmp::PartialOrd</code>, we need to specify
<code>PartialOrd</code> in the trait bounds for <code>T</code> so the <code>largest</code> function can work on
slices of any type that we can compare. We dont need to bring <code>PartialOrd</code>
into scope because its in the prelude. Change the signature of <code>largest</code> to
look like this:</p>
<pre><code class="language-rust ignore">fn largest&lt;T: PartialOrd&gt;(list: &amp;[T]) -&gt; T {
</code></pre>
<p>This time when we compile the code, we get a different set of errors:</p>
<pre><code class="language-text">error[E0508]: cannot move out of type `[T]`, a non-copy slice
--&gt; src/main.rs:2:23
|
2 | let mut largest = list[0];
| ^^^^^^^
| |
| cannot move out of here
| help: consider using a reference instead: `&amp;list[0]`
error[E0507]: cannot move out of borrowed content
--&gt; src/main.rs:4:9
|
4 | for &amp;item in list.iter() {
| ^----
| ||
| |hint: to prevent move, use `ref item` or `ref mut item`
| cannot move out of borrowed content
</code></pre>
<p>The key line in this error is <code>cannot move out of type [T], a non-copy slice</code>.
With our non-generic versions of the <code>largest</code> function, we were only trying to
find the largest <code>i32</code> or <code>char</code>. As discussed in the <a href="ch04-01-what-is-ownership.html#stack-only-data-copy">“Stack-Only Data:
Copy”</a><!-- ignore --> section in Chapter 4, types like
<code>i32</code> and <code>char</code> that have a known size can be stored on the stack, so they
implement the <code>Copy</code> trait. But when we made the <code>largest</code> function generic,
it became possible for the <code>list</code> parameter to have types in it that dont
implement the <code>Copy</code> trait. Consequently, we wouldnt be able to move the
value out of <code>list[0]</code> and into the <code>largest</code> variable, resulting in this
error.</p>
<p>To call this code with only those types that implement the <code>Copy</code> trait, we can
add <code>Copy</code> to the trait bounds of <code>T</code>! Listing 10-15 shows the complete code of
a generic <code>largest</code> function that will compile as long as the types of the
values in the slice that we pass into the function implement the <code>PartialOrd</code>
<em>and</em> <code>Copy</code> traits, like <code>i32</code> and <code>char</code> do.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">fn largest&lt;T: PartialOrd + Copy&gt;(list: &amp;[T]) -&gt; T {
let mut largest = list[0];
for &amp;item in list.iter() {
if item &gt; largest {
largest = item;
}
}
largest
}
fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let result = largest(&amp;number_list);
println!(&quot;The largest number is {}&quot;, result);
let char_list = vec!['y', 'm', 'a', 'q'];
let result = largest(&amp;char_list);
println!(&quot;The largest char is {}&quot;, result);
}
</code></pre></pre>
<p><span class="caption">Listing 10-15: A working definition of the <code>largest</code>
function that works on any generic type that implements the <code>PartialOrd</code> and
<code>Copy</code> traits</span></p>
<p>If we dont want to restrict the <code>largest</code> function to the types that implement
the <code>Copy</code> trait, we could specify that <code>T</code> has the trait bound <code>Clone</code> instead
of <code>Copy</code>. Then we could clone each value in the slice when we want the
<code>largest</code> function to have ownership. Using the <code>clone</code> function means were
potentially making more heap allocations in the case of types that own heap
data like <code>String</code>, and heap allocations can be slow if were working with
large amounts of data.</p>
<p>Another way we could implement <code>largest</code> is for the function to return a
reference to a <code>T</code> value in the slice. If we change the return type to <code>&amp;T</code>
instead of <code>T</code>, thereby changing the body of the function to return a
reference, we wouldnt need the <code>Clone</code> or <code>Copy</code> trait bounds and we could
avoid heap allocations. Try implementing these alternate solutions on your own!</p>
<h3><a class="header" href="#using-trait-bounds-to-conditionally-implement-methods" id="using-trait-bounds-to-conditionally-implement-methods">Using Trait Bounds to Conditionally Implement Methods</a></h3>
<p>By using a trait bound with an <code>impl</code> block that uses generic type parameters,
we can implement methods conditionally for types that implement the specified
traits. For example, the type <code>Pair&lt;T&gt;</code> in Listing 10-16 always implements the
<code>new</code> function. But <code>Pair&lt;T&gt;</code> only implements the <code>cmp_display</code> method if its
inner type <code>T</code> implements the <code>PartialOrd</code> trait that enables comparison <em>and</em>
the <code>Display</code> trait that enables printing.</p>
<pre><pre class="playpen"><code class="language-rust">
<span class="boring">#![allow(unused_variables)]
</span><span class="boring">fn main() {
</span>use std::fmt::Display;
struct Pair&lt;T&gt; {
x: T,
y: T,
}
impl&lt;T&gt; Pair&lt;T&gt; {
fn new(x: T, y: T) -&gt; Self {
Self {
x,
y,
}
}
}
impl&lt;T: Display + PartialOrd&gt; Pair&lt;T&gt; {
fn cmp_display(&amp;self) {
if self.x &gt;= self.y {
println!(&quot;The largest member is x = {}&quot;, self.x);
} else {
println!(&quot;The largest member is y = {}&quot;, self.y);
}
}
}
<span class="boring">}
</span></code></pre></pre>
<p><span class="caption">Listing 10-16: Conditionally implement methods on a
generic type depending on trait bounds</span></p>
<p>We can also conditionally implement a trait for any type that implements
another trait. Implementations of a trait on any type that satisfies the trait
bounds are called <em>blanket implementations</em> and are extensively used in the
Rust standard library. For example, the standard library implements the
<code>ToString</code> trait on any type that implements the <code>Display</code> trait. The <code>impl</code>
block in the standard library looks similar to this code:</p>
<pre><code class="language-rust ignore">impl&lt;T: Display&gt; ToString for T {
// --snip--
}
</code></pre>
<p>Because the standard library has this blanket implementation, we can call the
<code>to_string</code> method defined by the <code>ToString</code> trait on any type that implements
the <code>Display</code> trait. For example, we can turn integers into their corresponding
<code>String</code> values like this because integers implement <code>Display</code>:</p>
<pre><pre class="playpen"><code class="language-rust">
<span class="boring">#![allow(unused_variables)]
</span><span class="boring">fn main() {
</span>let s = 3.to_string();
<span class="boring">}
</span></code></pre></pre>
<p>Blanket implementations appear in the documentation for the trait in the
“Implementors” section.</p>
<p>Traits and trait bounds let us write code that uses generic type parameters to
reduce duplication but also specify to the compiler that we want the generic
type to have particular behavior. The compiler can then use the trait bound
information to check that all the concrete types used with our code provide the
correct behavior. In dynamically typed languages, we would get an error at
runtime if we called a method on a type which didnt implement the type which
defines the method. But Rust moves these errors to compile time so were forced
to fix the problems before our code is even able to run. Additionally, we dont
have to write code that checks for behavior at runtime because weve already
checked at compile time. Doing so improves performance without having to give
up the flexibility of generics.</p>
<p>Another kind of generic that weve already been using is called <em>lifetimes</em>.
Rather than ensuring that a type has the behavior we want, lifetimes ensure
that references are valid as long as we need them to be. Lets look at how
lifetimes do that.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="ch10-01-syntax.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="ch10-03-lifetime-syntax.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="ch10-01-syntax.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="ch10-03-lifetime-syntax.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>