745 lines
55 KiB
HTML
745 lines
55 KiB
HTML
<!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 Library’s 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 type’s 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, let’s 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(&self) -> 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 trait’s 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(&self) -> 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 we’ve 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(&self) -> 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(&self) -> String {
|
||
format!("{}, by {} ({})", 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(&self) -> String {
|
||
format!("{}: {}", 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("horse_ebooks"),
|
||
content: String::from("of course, as you probably already know, people"),
|
||
reply: false,
|
||
retweet: false,
|
||
};
|
||
|
||
println!("1 new tweet: {}", 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, they’re all in the same
|
||
scope. Let’s say this <em>lib.rs</em> is for a crate we’ve called <code>aggregator</code> and
|
||
someone else wants to use our crate’s functionality to implement the <code>Summary</code>
|
||
trait on a struct defined within their library’s 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<T></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 can’t implement external traits on external types. For example, we can’t
|
||
implement the <code>Display</code> trait on <code>Vec<T></code> within our <code>aggregator</code> crate,
|
||
because <code>Display</code> and <code>Vec<T></code> are defined in the standard library and aren’t
|
||
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 people’s
|
||
code can’t break your code and vice versa. Without the rule, two crates could
|
||
implement the same trait for the same type, and Rust wouldn’t know which
|
||
implementation to use.</p>
|
||
<h3><a class="header" href="#default-implementations" id="default-implementations">Default Implementations</a></h3>
|
||
<p>Sometimes it’s 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 method’s 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(&self) -> String {
|
||
String::from("(Read more...)")
|
||
}
|
||
}
|
||
<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 we’re no longer defining the <code>summarize</code> method on <code>NewsArticle</code>
|
||
directly, we’ve 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("Penguins win the Stanley Cup Championship!"),
|
||
location: String::from("Pittsburgh, PA, USA"),
|
||
author: String::from("Iceburgh"),
|
||
content: String::from("The Pittsburgh Penguins once again are the best
|
||
hockey team in the NHL."),
|
||
};
|
||
|
||
println!("New article available! {}", 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> doesn’t 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 doesn’t have a default
|
||
implementation.</p>
|
||
<p>Default implementations can call other methods in the same trait, even if those
|
||
other methods don’t 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(&self) -> String;
|
||
|
||
fn summarize(&self) -> String {
|
||
format!("(Read more from {}...)", 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(&self) -> String {
|
||
format!("@{}", 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 we’ve provided. Because we’ve 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("horse_ebooks"),
|
||
content: String::from("of course, as you probably already know, people"),
|
||
reply: false,
|
||
retweet: false,
|
||
};
|
||
|
||
println!("1 new tweet: {}", tweet.summarize());
|
||
</code></pre>
|
||
<p>This code prints <code>1 new tweet: (Read more from @horse_ebooks...)</code>.</p>
|
||
<p>Note that it isn’t 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!("Breaking news! {}", 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>, won’t compile
|
||
because those types don’t 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<T: Summary>(item: T) {
|
||
println!("Breaking news! {}", 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, that’s
|
||
only possible to express using a trait bound, like this:</p>
|
||
<pre><code class="language-rust ignore">pub fn notify<T: Summary>(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<T: Summary + Display>(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 function’s 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<T: Display + Clone, U: Clone + Debug>(t: T, u: U) -> i32 {
|
||
</code></pre>
|
||
<p>we can use a <code>where</code> clause, like this:</p>
|
||
<pre><code class="language-rust ignore">fn some_function<T, U>(t: T, u: U) -> i32
|
||
where T: Display + Clone,
|
||
U: Clone + Debug
|
||
{
|
||
</code></pre>
|
||
<p>This function’s 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() -> impl Summary {
|
||
Tweet {
|
||
username: String::from("horse_ebooks"),
|
||
content: String::from("of course, as you probably already know, people"),
|
||
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 doesn’t 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 you’re 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> wouldn’t work:</p>
|
||
<pre><code class="language-rust ignore does_not_compile">fn returns_summarizable(switch: bool) -> impl Summary {
|
||
if switch {
|
||
NewsArticle {
|
||
headline: String::from("Penguins win the Stanley Cup Championship!"),
|
||
location: String::from("Pittsburgh, PA, USA"),
|
||
author: String::from("Iceburgh"),
|
||
content: String::from("The Pittsburgh Penguins once again are the best
|
||
hockey team in the NHL."),
|
||
}
|
||
} else {
|
||
Tweet {
|
||
username: String::from("horse_ebooks"),
|
||
content: String::from("of course, as you probably already know, people"),
|
||
reply: false,
|
||
retweet: false,
|
||
}
|
||
}
|
||
}
|
||
</code></pre>
|
||
<p>Returning either a <code>NewsArticle</code> or a <code>Tweet</code> isn’t allowed due to restrictions
|
||
around how the <code>impl Trait</code> syntax is implemented in the compiler. We’ll 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 parameter’s bounds, let’s 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 `>` cannot be applied to type `T`
|
||
--> src/main.rs:5:12
|
||
|
|
||
5 | if item > 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>></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 don’t need to bring <code>PartialOrd</code>
|
||
into scope because it’s in the prelude. Change the signature of <code>largest</code> to
|
||
look like this:</p>
|
||
<pre><code class="language-rust ignore">fn largest<T: PartialOrd>(list: &[T]) -> 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
|
||
--> src/main.rs:2:23
|
||
|
|
||
2 | let mut largest = list[0];
|
||
| ^^^^^^^
|
||
| |
|
||
| cannot move out of here
|
||
| help: consider using a reference instead: `&list[0]`
|
||
|
||
error[E0507]: cannot move out of borrowed content
|
||
--> src/main.rs:4:9
|
||
|
|
||
4 | for &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 don’t
|
||
implement the <code>Copy</code> trait. Consequently, we wouldn’t 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<T: PartialOrd + Copy>(list: &[T]) -> T {
|
||
let mut largest = list[0];
|
||
|
||
for &item in list.iter() {
|
||
if item > largest {
|
||
largest = item;
|
||
}
|
||
}
|
||
|
||
largest
|
||
}
|
||
|
||
fn main() {
|
||
let number_list = vec![34, 50, 25, 100, 65];
|
||
|
||
let result = largest(&number_list);
|
||
println!("The largest number is {}", result);
|
||
|
||
let char_list = vec!['y', 'm', 'a', 'q'];
|
||
|
||
let result = largest(&char_list);
|
||
println!("The largest char is {}", 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 don’t 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 we’re
|
||
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 we’re 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>&T</code>
|
||
instead of <code>T</code>, thereby changing the body of the function to return a
|
||
reference, we wouldn’t 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<T></code> in Listing 10-16 always implements the
|
||
<code>new</code> function. But <code>Pair<T></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<T> {
|
||
x: T,
|
||
y: T,
|
||
}
|
||
|
||
impl<T> Pair<T> {
|
||
fn new(x: T, y: T) -> Self {
|
||
Self {
|
||
x,
|
||
y,
|
||
}
|
||
}
|
||
}
|
||
|
||
impl<T: Display + PartialOrd> Pair<T> {
|
||
fn cmp_display(&self) {
|
||
if self.x >= self.y {
|
||
println!("The largest member is x = {}", self.x);
|
||
} else {
|
||
println!("The largest member is y = {}", 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<T: Display> 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 didn’t implement the type which
|
||
defines the method. But Rust moves these errors to compile time so we’re forced
|
||
to fix the problems before our code is even able to run. Additionally, we don’t
|
||
have to write code that checks for behavior at runtime because we’ve 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 we’ve 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. Let’s 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>
|