RustBook/ch19-03-advanced-traits.html

814 lines
57 KiB
HTML
Raw Permalink Normal View History

2020-01-06 20:57:15 +00:00
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Advanced Traits - 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"><
</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="#advanced-traits" id="advanced-traits">Advanced Traits</a></h2>
<p>We first covered traits in the <a href="ch10-02-traits.html#traits-defining-shared-behavior">“Traits: Defining Shared
Behavior”</a><!-- ignore --> section of Chapter
10, but as with lifetimes, we didnt discuss the more advanced details. Now
that you know more about Rust, we can get into the nitty-gritty.</p>
<h3><a class="header" href="#specifying-placeholder-types-in-trait-definitions-with-associated-types" id="specifying-placeholder-types-in-trait-definitions-with-associated-types">Specifying Placeholder Types in Trait Definitions with Associated Types</a></h3>
<p><em>Associated types</em> connect a type placeholder with a trait such that the trait
method definitions can use these placeholder types in their signatures. The
implementor of a trait will specify the concrete type to be used in this types
place for the particular implementation. That way, we can define a trait that
uses some types without needing to know exactly what those types are until the
trait is implemented.</p>
<p>Weve described most of the advanced features in this chapter as being rarely
needed. Associated types are somewhere in the middle: theyre used more rarely
than features explained in the rest of the book but more commonly than many of
the other features discussed in this chapter.</p>
<p>One example of a trait with an associated type is the <code>Iterator</code> trait that the
standard library provides. The associated type is named <code>Item</code> and stands in
for the type of the values the type implementing the <code>Iterator</code> trait is
iterating over. In <a href="ch13-02-iterators.html#the-iterator-trait-and-the-next-method">“The <code>Iterator</code> Trait and the <code>next</code>
Method”</a><!-- ignore --> section of
Chapter 13, we mentioned that the definition of the <code>Iterator</code> trait is as
shown in Listing 19-12.</p>
<pre><pre class="playpen"><code class="language-rust">
<span class="boring">#![allow(unused_variables)]
</span><span class="boring">fn main() {
</span>pub trait Iterator {
type Item;
fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt;;
}
<span class="boring">}
</span></code></pre></pre>
<p><span class="caption">Listing 19-12: The definition of the <code>Iterator</code> trait
that has an associated type <code>Item</code></span></p>
<p>The type <code>Item</code> is a placeholder type, and the <code>next</code> methods definition shows
that it will return values of type <code>Option&lt;Self::Item&gt;</code>. Implementors of the
<code>Iterator</code> trait will specify the concrete type for <code>Item</code>, and the <code>next</code>
method will return an <code>Option</code> containing a value of that concrete type.</p>
<p>Associated types might seem like a similar concept to generics, in that the
latter allow us to define a function without specifying what types it can
handle. So why use associated types?</p>
<p>Lets examine the difference between the two concepts with an example from
Chapter 13 that implements the <code>Iterator</code> trait on the <code>Counter</code> struct. In
Listing 13-21, we specified that the <code>Item</code> type was <code>u32</code>:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><code class="language-rust ignore">impl Iterator for Counter {
type Item = u32;
fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
// --snip--
</code></pre>
<p>This syntax seems comparable to that of generics. So why not just define the
<code>Iterator</code> trait with generics, as shown in Listing 19-13?</p>
<pre><pre class="playpen"><code class="language-rust">
<span class="boring">#![allow(unused_variables)]
</span><span class="boring">fn main() {
</span>pub trait Iterator&lt;T&gt; {
fn next(&amp;mut self) -&gt; Option&lt;T&gt;;
}
<span class="boring">}
</span></code></pre></pre>
<p><span class="caption">Listing 19-13: A hypothetical definition of the
<code>Iterator</code> trait using generics</span></p>
<p>The difference is that when using generics, as in Listing 19-13, we must
annotate the types in each implementation; because we can also implement
<code>Iterator&lt;String&gt; for Counter</code> or any other type, we could have multiple
implementations of <code>Iterator</code> for <code>Counter</code>. In other words, when a trait has a
generic parameter, it can be implemented for a type multiple times, changing
the concrete types of the generic type parameters each time. When we use the
<code>next</code> method on <code>Counter</code>, we would have to provide type annotations to
indicate which implementation of <code>Iterator</code> we want to use.</p>
<p>With associated types, we dont need to annotate types because we cant
implement a trait on a type multiple times. In Listing 19-12 with the
definition that uses associated types, we can only choose what the type of
<code>Item</code> will be once, because there can only be one <code>impl Iterator for Counter</code>.
We dont have to specify that we want an iterator of <code>u32</code> values everywhere
that we call <code>next</code> on <code>Counter</code>.</p>
<h3><a class="header" href="#default-generic-type-parameters-and-operator-overloading" id="default-generic-type-parameters-and-operator-overloading">Default Generic Type Parameters and Operator Overloading</a></h3>
<p>When we use generic type parameters, we can specify a default concrete type for
the generic type. This eliminates the need for implementors of the trait to
specify a concrete type if the default type works. The syntax for specifying a
default type for a generic type is <code>&lt;PlaceholderType=ConcreteType&gt;</code> when
declaring the generic type.</p>
<p>A great example of a situation where this technique is useful is with operator
overloading. <em>Operator overloading</em> is customizing the behavior of an operator
(such as <code>+</code>) in particular situations.</p>
<p>Rust doesnt allow you to create your own operators or overload arbitrary
operators. But you can overload the operations and corresponding traits listed
in <code>std::ops</code> by implementing the traits associated with the operator. For
example, in Listing 19-14 we overload the <code>+</code> operator to add two <code>Point</code>
instances together. We do this by implementing the <code>Add</code> trait on a <code>Point</code>
struct:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">use std::ops::Add;
#[derive(Debug, PartialEq)]
struct Point {
x: i32,
y: i32,
}
impl Add for Point {
type Output = Point;
fn add(self, other: Point) -&gt; Point {
Point {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
fn main() {
assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
Point { x: 3, y: 3 });
}
</code></pre></pre>
<p><span class="caption">Listing 19-14: Implementing the <code>Add</code> trait to overload
the <code>+</code> operator for <code>Point</code> instances</span></p>
<p>The <code>add</code> method adds the <code>x</code> values of two <code>Point</code> instances and the <code>y</code>
values of two <code>Point</code> instances to create a new <code>Point</code>. The <code>Add</code> trait has an
associated type named <code>Output</code> that determines the type returned from the <code>add</code>
method.</p>
<p>The default generic type in this code is within the <code>Add</code> trait. Here is its
definition:</p>
<pre><pre class="playpen"><code class="language-rust">
<span class="boring">#![allow(unused_variables)]
</span><span class="boring">fn main() {
</span>trait Add&lt;RHS=Self&gt; {
type Output;
fn add(self, rhs: RHS) -&gt; Self::Output;
}
<span class="boring">}
</span></code></pre></pre>
<p>This code should look generally familiar: a trait with one method and an
associated type. The new part is <code>RHS=Self</code>: this syntax is called <em>default
type parameters</em>. The <code>RHS</code> generic type parameter (short for “right hand
side”) defines the type of the <code>rhs</code> parameter in the <code>add</code> method. If we dont
specify a concrete type for <code>RHS</code> when we implement the <code>Add</code> trait, the type
of <code>RHS</code> will default to <code>Self</code>, which will be the type were implementing
<code>Add</code> on.</p>
<p>When we implemented <code>Add</code> for <code>Point</code>, we used the default for <code>RHS</code> because we
wanted to add two <code>Point</code> instances. Lets look at an example of implementing
the <code>Add</code> trait where we want to customize the <code>RHS</code> type rather than using the
default.</p>
<p>We have two structs, <code>Millimeters</code> and <code>Meters</code>, holding values in different
units. We want to add values in millimeters to values in meters and have the
implementation of <code>Add</code> do the conversion correctly. We can implement <code>Add</code> for
<code>Millimeters</code> with <code>Meters</code> as the <code>RHS</code>, as shown in Listing 19-15.</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>use std::ops::Add;
struct Millimeters(u32);
struct Meters(u32);
impl Add&lt;Meters&gt; for Millimeters {
type Output = Millimeters;
fn add(self, other: Meters) -&gt; Millimeters {
Millimeters(self.0 + (other.0 * 1000))
}
}
<span class="boring">}
</span></code></pre></pre>
<p><span class="caption">Listing 19-15: Implementing the <code>Add</code> trait on
<code>Millimeters</code> to add <code>Millimeters</code> to <code>Meters</code></span></p>
<p>To add <code>Millimeters</code> and <code>Meters</code>, we specify <code>impl Add&lt;Meters&gt;</code> to set the
value of the <code>RHS</code> type parameter instead of using the default of <code>Self</code>.</p>
<p>Youll use default type parameters in two main ways:</p>
<ul>
<li>To extend a type without breaking existing code</li>
<li>To allow customization in specific cases most users wont need</li>
</ul>
<p>The standard librarys <code>Add</code> trait is an example of the second purpose:
usually, youll add two like types, but the <code>Add</code> trait provides the ability to
customize beyond that. Using a default type parameter in the <code>Add</code> trait
definition means you dont have to specify the extra parameter most of the
time. In other words, a bit of implementation boilerplate isnt needed, making
it easier to use the trait.</p>
<p>The first purpose is similar to the second but in reverse: if you want to add a
type parameter to an existing trait, you can give it a default to allow
extension of the functionality of the trait without breaking the existing
implementation code.</p>
<h3><a class="header" href="#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name" id="fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name">Fully Qualified Syntax for Disambiguation: Calling Methods with the Same Name</a></h3>
<p>Nothing in Rust prevents a trait from having a method with the same name as
another traits method, nor does Rust prevent you from implementing both traits
on one type. Its also possible to implement a method directly on the type with
the same name as methods from traits.</p>
<p>When calling methods with the same name, youll need to tell Rust which one you
want to use. Consider the code in Listing 19-16 where weve defined two traits,
<code>Pilot</code> and <code>Wizard</code>, that both have a method called <code>fly</code>. We then implement
both traits on a type <code>Human</code> that already has a method named <code>fly</code> implemented
on it. Each <code>fly</code> method does something different.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">
<span class="boring">#![allow(unused_variables)]
</span><span class="boring">fn main() {
</span>trait Pilot {
fn fly(&amp;self);
}
trait Wizard {
fn fly(&amp;self);
}
struct Human;
impl Pilot for Human {
fn fly(&amp;self) {
println!(&quot;This is your captain speaking.&quot;);
}
}
impl Wizard for Human {
fn fly(&amp;self) {
println!(&quot;Up!&quot;);
}
}
impl Human {
fn fly(&amp;self) {
println!(&quot;*waving arms furiously*&quot;);
}
}
<span class="boring">}
</span></code></pre></pre>
<p><span class="caption">Listing 19-16: Two traits are defined to have a <code>fly</code>
method and are implemented on the <code>Human</code> type, and a <code>fly</code> method is
implemented on <code>Human</code> directly</span></p>
<p>When we call <code>fly</code> on an instance of <code>Human</code>, the compiler defaults to calling
the method that is directly implemented on the type, as shown in Listing 19-17.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust"><span class="boring">trait Pilot {
</span><span class="boring"> fn fly(&amp;self);
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">trait Wizard {
</span><span class="boring"> fn fly(&amp;self);
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">struct Human;
</span><span class="boring">
</span><span class="boring">impl Pilot for Human {
</span><span class="boring"> fn fly(&amp;self) {
</span><span class="boring"> println!(&quot;This is your captain speaking.&quot;);
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Wizard for Human {
</span><span class="boring"> fn fly(&amp;self) {
</span><span class="boring"> println!(&quot;Up!&quot;);
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Human {
</span><span class="boring"> fn fly(&amp;self) {
</span><span class="boring"> println!(&quot;*waving arms furiously*&quot;);
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span>fn main() {
let person = Human;
person.fly();
}
</code></pre></pre>
<p><span class="caption">Listing 19-17: Calling <code>fly</code> on an instance of
<code>Human</code></span></p>
<p>Running this code will print <code>*waving arms furiously*</code>, showing that Rust
called the <code>fly</code> method implemented on <code>Human</code> directly.</p>
<p>To call the <code>fly</code> methods from either the <code>Pilot</code> trait or the <code>Wizard</code> trait,
we need to use more explicit syntax to specify which <code>fly</code> method we mean.
Listing 19-18 demonstrates this syntax.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust"><span class="boring">trait Pilot {
</span><span class="boring"> fn fly(&amp;self);
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">trait Wizard {
</span><span class="boring"> fn fly(&amp;self);
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">struct Human;
</span><span class="boring">
</span><span class="boring">impl Pilot for Human {
</span><span class="boring"> fn fly(&amp;self) {
</span><span class="boring"> println!(&quot;This is your captain speaking.&quot;);
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Wizard for Human {
</span><span class="boring"> fn fly(&amp;self) {
</span><span class="boring"> println!(&quot;Up!&quot;);
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Human {
</span><span class="boring"> fn fly(&amp;self) {
</span><span class="boring"> println!(&quot;*waving arms furiously*&quot;);
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span>fn main() {
let person = Human;
Pilot::fly(&amp;person);
Wizard::fly(&amp;person);
person.fly();
}
</code></pre></pre>
<p><span class="caption">Listing 19-18: Specifying which traits <code>fly</code> method we
want to call</span></p>
<p>Specifying the trait name before the method name clarifies to Rust which
implementation of <code>fly</code> we want to call. We could also write
<code>Human::fly(&amp;person)</code>, which is equivalent to the <code>person.fly()</code> that we used
in Listing 19-18, but this is a bit longer to write if we dont need to
disambiguate.</p>
<p>Running this code prints the following:</p>
<pre><code class="language-text">This is your captain speaking.
Up!
*waving arms furiously*
</code></pre>
<p>Because the <code>fly</code> method takes a <code>self</code> parameter, if we had two <em>types</em> that
both implement one <em>trait</em>, Rust could figure out which implementation of a
trait to use based on the type of <code>self</code>.</p>
<p>However, associated functions that are part of traits dont have a <code>self</code>
parameter. When two types in the same scope implement that trait, Rust cant
figure out which type you mean unless you use <em>fully qualified syntax</em>. For
example, the <code>Animal</code> trait in Listing 19-19 has the associated function
<code>baby_name</code>, the implementation of <code>Animal</code> for the struct <code>Dog</code>, and the
associated function <code>baby_name</code> defined on <code>Dog</code> directly.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">trait Animal {
fn baby_name() -&gt; String;
}
struct Dog;
impl Dog {
fn baby_name() -&gt; String {
String::from(&quot;Spot&quot;)
}
}
impl Animal for Dog {
fn baby_name() -&gt; String {
String::from(&quot;puppy&quot;)
}
}
fn main() {
println!(&quot;A baby dog is called a {}&quot;, Dog::baby_name());
}
</code></pre></pre>
<p><span class="caption">Listing 19-19: A trait with an associated function and a
type with an associated function of the same name that also implements the
trait</span></p>
<p>This code is for an animal shelter that wants to name all puppies Spot, which
is implemented in the <code>baby_name</code> associated function that is defined on <code>Dog</code>.
The <code>Dog</code> type also implements the trait <code>Animal</code>, which describes
characteristics that all animals have. Baby dogs are called puppies, and that
is expressed in the implementation of the <code>Animal</code> trait on <code>Dog</code> in the
<code>baby_name</code> function associated with the <code>Animal</code> trait.</p>
<p>In <code>main</code>, we call the <code>Dog::baby_name</code> function, which calls the associated
function defined on <code>Dog</code> directly. This code prints the following:</p>
<pre><code class="language-text">A baby dog is called a Spot
</code></pre>
<p>This output isnt what we wanted. We want to call the <code>baby_name</code> function that
is part of the <code>Animal</code> trait that we implemented on <code>Dog</code> so the code prints
<code>A baby dog is called a puppy</code>. The technique of specifying the trait name that
we used in Listing 19-18 doesnt help here; if we change <code>main</code> to the code in
Listing 19-20, well get a compilation error.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust ignore does_not_compile">fn main() {
println!(&quot;A baby dog is called a {}&quot;, Animal::baby_name());
}
</code></pre>
<p><span class="caption">Listing 19-20: Attempting to call the <code>baby_name</code>
function from the <code>Animal</code> trait, but Rust doesnt know which implementation to
use</span></p>
<p>Because <code>Animal::baby_name</code> is an associated function rather than a method, and
thus doesnt have a <code>self</code> parameter, Rust cant figure out which
implementation of <code>Animal::baby_name</code> we want. Well get this compiler error:</p>
<pre><code class="language-text">error[E0283]: type annotations required: cannot resolve `_: Animal`
--&gt; src/main.rs:20:43
|
20 | println!(&quot;A baby dog is called a {}&quot;, Animal::baby_name());
| ^^^^^^^^^^^^^^^^^
|
= note: required by `Animal::baby_name`
</code></pre>
<p>To disambiguate and tell Rust that we want to use the implementation of
<code>Animal</code> for <code>Dog</code>, we need to use fully qualified syntax. Listing 19-21
demonstrates how to use fully qualified syntax.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust"><span class="boring">trait Animal {
</span><span class="boring"> fn baby_name() -&gt; String;
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">struct Dog;
</span><span class="boring">
</span><span class="boring">impl Dog {
</span><span class="boring"> fn baby_name() -&gt; String {
</span><span class="boring"> String::from(&quot;Spot&quot;)
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Animal for Dog {
</span><span class="boring"> fn baby_name() -&gt; String {
</span><span class="boring"> String::from(&quot;puppy&quot;)
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span>fn main() {
println!(&quot;A baby dog is called a {}&quot;, &lt;Dog as Animal&gt;::baby_name());
}
</code></pre></pre>
<p><span class="caption">Listing 19-21: Using fully qualified syntax to specify
that we want to call the <code>baby_name</code> function from the <code>Animal</code> trait as
implemented on <code>Dog</code></span></p>
<p>Were providing Rust with a type annotation within the angle brackets, which
indicates we want to call the <code>baby_name</code> method from the <code>Animal</code> trait as
implemented on <code>Dog</code> by saying that we want to treat the <code>Dog</code> type as an
<code>Animal</code> for this function call. This code will now print what we want:</p>
<pre><code class="language-text">A baby dog is called a puppy
</code></pre>
<p>In general, fully qualified syntax is defined as follows:</p>
<pre><code class="language-rust ignore">&lt;Type as Trait&gt;::function(receiver_if_method, next_arg, ...);
</code></pre>
<p>For associated functions, there would not be a <code>receiver</code>: there would only be
the list of other arguments. You could use fully qualified syntax everywhere
that you call functions or methods. However, youre allowed to omit any part of
this syntax that Rust can figure out from other information in the program. You
only need to use this more verbose syntax in cases where there are multiple
implementations that use the same name and Rust needs help to identify which
implementation you want to call.</p>
<h3><a class="header" href="#using-supertraits-to-require-one-traits-functionality-within-another-trait" id="using-supertraits-to-require-one-traits-functionality-within-another-trait">Using Supertraits to Require One Traits Functionality Within Another Trait</a></h3>
<p>Sometimes, you might need one trait to use another traits functionality. In
this case, you need to rely on the dependent trait also being implemented.
The trait you rely on is a <em>supertrait</em> of the trait youre implementing.</p>
<p>For example, lets say we want to make an <code>OutlinePrint</code> trait with an
<code>outline_print</code> method that will print a value framed in asterisks. That is,
given a <code>Point</code> struct that implements <code>Display</code> to result in <code>(x, y)</code>, when we
call <code>outline_print</code> on a <code>Point</code> instance that has <code>1</code> for <code>x</code> and <code>3</code> for
<code>y</code>, it should print the following:</p>
<pre><code class="language-text">**********
* *
* (1, 3) *
* *
**********
</code></pre>
<p>In the implementation of <code>outline_print</code>, we want to use the <code>Display</code> traits
functionality. Therefore, we need to specify that the <code>OutlinePrint</code> trait will
work only for types that also implement <code>Display</code> and provide the functionality
that <code>OutlinePrint</code> needs. We can do that in the trait definition by specifying
<code>OutlinePrint: Display</code>. This technique is similar to adding a trait bound to
the trait. Listing 19-22 shows an implementation of the <code>OutlinePrint</code> trait.</p>
<p><span class="filename">Filename: src/main.rs</span></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;
trait OutlinePrint: fmt::Display {
fn outline_print(&amp;self) {
let output = self.to_string();
let len = output.len();
println!(&quot;{}&quot;, &quot;*&quot;.repeat(len + 4));
println!(&quot;*{}*&quot;, &quot; &quot;.repeat(len + 2));
println!(&quot;* {} *&quot;, output);
println!(&quot;*{}*&quot;, &quot; &quot;.repeat(len + 2));
println!(&quot;{}&quot;, &quot;*&quot;.repeat(len + 4));
}
}
<span class="boring">}
</span></code></pre></pre>
<p><span class="caption">Listing 19-22: Implementing the <code>OutlinePrint</code> trait that
requires the functionality from <code>Display</code></span></p>
<p>Because weve specified that <code>OutlinePrint</code> requires the <code>Display</code> trait, we
can use the <code>to_string</code> function that is automatically implemented for any type
that implements <code>Display</code>. If we tried to use <code>to_string</code> without adding a
colon and specifying the <code>Display</code> trait after the trait name, wed get an
error saying that no method named <code>to_string</code> was found for the type <code>&amp;Self</code> in
the current scope.</p>
<p>Lets see what happens when we try to implement <code>OutlinePrint</code> on a type that
doesnt implement <code>Display</code>, such as the <code>Point</code> struct:</p>
<p><span class="filename">Filename: src/main.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">trait OutlinePrint {}
</span>struct Point {
x: i32,
y: i32,
}
impl OutlinePrint for Point {}
<span class="boring">}
</span></code></pre></pre>
<p>We get an error saying that <code>Display</code> is required but not implemented:</p>
<pre><code class="language-text">error[E0277]: the trait bound `Point: std::fmt::Display` is not satisfied
--&gt; src/main.rs:20:6
|
20 | impl OutlinePrint for Point {}
| ^^^^^^^^^^^^ `Point` cannot be formatted with the default formatter;
try using `:?` instead if you are using a format string
|
= help: the trait `std::fmt::Display` is not implemented for `Point`
</code></pre>
<p>To fix this, we implement <code>Display</code> on <code>Point</code> and satisfy the constraint that
<code>OutlinePrint</code> requires, like so:</p>
<p><span class="filename">Filename: src/main.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">struct Point {
</span><span class="boring"> x: i32,
</span><span class="boring"> y: i32,
</span><span class="boring">}
</span><span class="boring">
</span>use std::fmt;
impl fmt::Display for Point {
fn fmt(&amp;self, f: &amp;mut fmt::Formatter) -&gt; fmt::Result {
write!(f, &quot;({}, {})&quot;, self.x, self.y)
}
}
<span class="boring">}
</span></code></pre></pre>
<p>Then implementing the <code>OutlinePrint</code> trait on <code>Point</code> will compile
successfully, and we can call <code>outline_print</code> on a <code>Point</code> instance to display
it within an outline of asterisks.</p>
<h3><a class="header" href="#using-the-newtype-pattern-to-implement-external-traits-on-external-types" id="using-the-newtype-pattern-to-implement-external-traits-on-external-types">Using the Newtype Pattern to Implement External Traits on External Types</a></h3>
<p>In Chapter 10 in the <a href="ch10-02-traits.html#implementing-a-trait-on-a-type">“Implementing a Trait on a
Type”</a><!-- ignore --> section, we mentioned
the orphan rule that states were allowed to implement a trait on a type as
long as either the trait or the type are local to our crate. Its possible to
get around this restriction using the <em>newtype pattern</em>, which involves
creating a new type in a tuple struct. (We covered tuple structs in the
<a href="ch05-01-defining-structs.html#using-tuple-structs-without-named-fields-to-create-different-types">“Using Tuple Structs without Named Fields to Create Different
Types”</a><!-- ignore --> section of Chapter 5.) The tuple struct
will have one field and be a thin wrapper around the type we want to implement
a trait for. Then the wrapper type is local to our crate, and we can implement
the trait on the wrapper. <em>Newtype</em> is a term that originates from the Haskell
programming language. There is no runtime performance penalty for using this
pattern, and the wrapper type is elided at compile time.</p>
<p>As an example, lets say we want to implement <code>Display</code> on <code>Vec&lt;T&gt;</code>, which the
orphan rule prevents us from doing directly because the <code>Display</code> trait and the
<code>Vec&lt;T&gt;</code> type are defined outside our crate. We can make a <code>Wrapper</code> struct
that holds an instance of <code>Vec&lt;T&gt;</code>; then we can implement <code>Display</code> on
<code>Wrapper</code> and use the <code>Vec&lt;T&gt;</code> value, as shown in Listing 19-23.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">use std::fmt;
struct Wrapper(Vec&lt;String&gt;);
impl fmt::Display for Wrapper {
fn fmt(&amp;self, f: &amp;mut fmt::Formatter) -&gt; fmt::Result {
write!(f, &quot;[{}]&quot;, self.0.join(&quot;, &quot;))
}
}
fn main() {
let w = Wrapper(vec![String::from(&quot;hello&quot;), String::from(&quot;world&quot;)]);
println!(&quot;w = {}&quot;, w);
}
</code></pre></pre>
<p><span class="caption">Listing 19-23: Creating a <code>Wrapper</code> type around
<code>Vec&lt;String&gt;</code> to implement <code>Display</code></span></p>
<p>The implementation of <code>Display</code> uses <code>self.0</code> to access the inner <code>Vec&lt;T&gt;</code>,
because <code>Wrapper</code> is a tuple struct and <code>Vec&lt;T&gt;</code> is the item at index 0 in the
tuple. Then we can use the functionality of the <code>Display</code> type on <code>Wrapper</code>.</p>
<p>The downside of using this technique is that <code>Wrapper</code> is a new type, so it
doesnt have the methods of the value its holding. We would have to implement
all the methods of <code>Vec&lt;T&gt;</code> directly on <code>Wrapper</code> such that the methods
delegate to <code>self.0</code>, which would allow us to treat <code>Wrapper</code> exactly like a
<code>Vec&lt;T&gt;</code>. If we wanted the new type to have every method the inner type has,
implementing the <code>Deref</code> trait (discussed in Chapter 15 in the <a href="ch15-02-deref.html#treating-smart-pointers-like-regular-references-with-the-deref-trait">“Treating Smart
Pointers Like Regular References with the <code>Deref</code>
Trait”</a><!-- ignore --> section) on the <code>Wrapper</code> to return
the inner type would be a solution. If we dont want the <code>Wrapper</code> type to have
all the methods of the inner type—for example, to restrict the <code>Wrapper</code> types
behavior—we would have to implement just the methods we do want manually.</p>
<p>Now you know how the newtype pattern is used in relation to traits; its also a
useful pattern even when traits are not involved. Lets switch focus and look
at some advanced ways to interact with Rusts type system.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="ch19-01-unsafe-rust.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="ch19-04-advanced-types.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="ch19-01-unsafe-rust.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="ch19-04-advanced-types.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>